<?php
namespace App\AtechNet\CoreBundle\Controller;
use App\AtechNet\CoreBundle\Entity\Attribute;
use App\AtechNet\CoreBundle\Entity\AttributeOption;
use App\AtechNet\CoreBundle\Entity\AttributeOptionMeta;
use App\AtechNet\CoreBundle\Entity\Basket;
use App\AtechNet\CoreBundle\Entity\BasketItem;
use App\AtechNet\CoreBundle\Entity\BasketItemAttributeOption;
use App\AtechNet\CoreBundle\Entity\Coupon;
use App\AtechNet\CoreBundle\Entity\Customer;
use App\AtechNet\CoreBundle\Entity\Domain;
use App\AtechNet\CoreBundle\Entity\DomainPaymentType;
use App\AtechNet\CoreBundle\Entity\DomainShippingType;
use App\AtechNet\CoreBundle\Entity\Product;
use App\AtechNet\CoreBundle\Entity\ProductType;
use App\AtechNet\CoreBundle\Entity\Vendor;
use App\AtechNet\CoreBundle\Enum\PaymentType;
use App\AtechNet\CoreBundle\Helper\Furbify\CartHelper;
use App\AtechNet\CoreBundle\Helper\Furbify\Image;
use App\AtechNet\CoreBundle\Helper\Furbify\MultiStore;
use App\AtechNet\CoreBundle\Helper\Packeta;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class CartController extends AbstractController
{
public const TIMEOUT = 2; // hours
private $unWantedAttributes = [
237, 239, 247, 241, 387, 388, 405, 409, 415, 419, 529, 854, 940, 1522, 1523, 1536, 1537,
];
/**
* @Route("/cart", name="cart_show", defaults={"_locale":""})
* @Route("/{_locale<%supported_locales%>?}/cart", name="cart_show_locale", defaults={"_locale":""})
* @param Request $request
* @return Response
* @throws \Exception
*/
public function showAction(Request $request)
{
$request->getSession()->remove('abandonedCart');
$data = [];
$domain = $this->getMultiStoreHelper($request)->getDomain();
$data['phone_support'] = $this->getContactInfos()["phone.webshop.{$domain->getLanguage()->getCode()}.{$domain->getType()}"];
$lastRemovedCartItem = $request->getSession()->get('lastRemovedCartItem');
if (!empty($lastRemovedCartItem)) {
$data['removedItem'] = $lastRemovedCartItem;
$data['removedItem']['href'] = $this->url($request)->link('product', [
'product_id' => $lastRemovedCartItem['productId'],
]);
}
$data['domainId'] = 0;
$data['header'] = $this->getHeader($request);
$data['footer'] = $this->getFooter($request);
$data['contentBottom'] = $this->getContentBottom($request);
$data['stepsOptions'] = $this->checkoutSteps(1);
$data['hideChat'] = true;
$cartId = $request->getSession()->get('cartId');
$isAbandoned = false;
$hasLoginError = null;
$entityManager = $this->getEntityManager();
if ($request->get('pi') && $request->get('pi') != '') {
$abandonedCartData = json_decode(base64_decode($request->get('pi')));
$cartId = $abandonedCartData->id;
$isAbandoned = true;
$request->getSession()->set('abandonedCart', $abandonedCartData);
// Check if customer has to be logged in
if (property_exists($abandonedCartData, "customerId")) {
$hasLoginError = $this->checkCustomerLoginStatusForAbandonedCart($request, $abandonedCartData);
}
}
if (!is_null($hasLoginError)) {
$data['loginError'] = $hasLoginError;
if ($hasLoginError == 'redirectToLogin') {
return $this->redirectToRoute('customer_login', [
'pi' => $request->get('pi'),
]);
}
return $this->render('AtechNetCoreBundle/Checkout/cart.html.twig', $data);
}
/**
* @var Basket $cart
*/
$cart = $isAbandoned ? $this->getAbandonedCart($cartId) : $this->getCart($cartId);
if (!$cart) {
return $this->render('AtechNetCoreBundle/Checkout/cart.html.twig', $data);
}
$request->getSession()->set('cartId', $cartId);
if ($isAbandoned) {
$cart->setUpdated((new \DateTime('NOW')));
$cart->setActive(true);
$entityManager->flush();
}
// Basket expires in...
$expire = $cart->getUpdated()->add(new \DateInterval("PT" . self::TIMEOUT . "H"));
// Empty Basket
// if (!$isAbandoned && $expire <= (new \DateTime('NOW'))) {
// $entityManager->remove($cart);
// $entityManager->flush();
// return $this->redirectToRoute('cart_show');
// }
$multiStore = $this->getMultiStoreHelper($request);
$domainId = $multiStore->getDomainId();
$data['currency'] = $domain->getCurrency();
$data['precision'] = $domain->getPricePrecision();
$placeholder = $this->getImage('placeholder.jpg', '')->resize(Image::PRODUCT_CART_THUMB_WIDTH, Image::PRODUCT_CART_THUMB_HEIGHT);
$data['stock'] = true;
$data['total'] = 0;
$data['subTotal'] = 0;
$data['items'] = [];
$data['marketingProductsGA4'] = '';
$data['cartBackToProductsLink'] = $request->getSession()->get('cartBackToProductsLink');
$customer = $this->getLoginHelper($request)->getLoggedInCustomer();
$useZeroVat = $this->useZeroVat($customer, $request);
$productHelper = $this->getProductHelper($request);
$databaseTranslator = $this->getDatabaseTranslator($request);
$enableFreeShipping = false;
/**
* @var BasketItem $item
*/
foreach ($cart->getBasketItems() as $index => $item) {
$itemProduct = $item->getProduct();
$product = $productHelper->getStructuredDataForProduct($itemProduct, 'cart');
if ($product) {
if (isset($customer) && $customer->getId() == Customer::MAXMEDIA_KFT_ID) {
$product['vatPrice'] = $domain->createVatPrice($product['rawPrice'], 1.27);
if ($product['isDiscounted']) {
$product['discountVatPrice'] = $domain->createVatPrice($product['rawDiscountPrice'], 1.27);
}
}
$stock = true;
$image = $placeholder;
if (is_object($product['images'])) {
$image = $this->getImage($product['images'], 'product/' . $product['code'])->resize(Image::PRODUCT_CART_THUMB_WIDTH, Image::PRODUCT_CART_THUMB_HEIGHT);
}
// Cross-sell Attribute Options
$crossSellAttributeOptions = CartHelper::getCrossSellAttributeOptionsByProductTypeId($product['productTypeId'], $domain->getId());
$options = [];
$optionPrice = $optionPriceValue = $optionSpecialValue = 0;
if (in_array($domainId, MultiStore::getWholesaleDomainIDs())){
$norton = $item->getItemAttributes()->filter(function (BasketItemAttributeOption $attribute) {
return $attribute->getAttributeOption()->getId() == AttributeOption::ATTRIBUTE_OPTION_ID_NORTON_ANTIVIRUS_FREE;
})->first();
if ($norton){
$item->getItemAttributes()->removeElement($norton);
$entityManager->persist($item);
$entityManager->flush();
}
}
foreach ($item->getItemAttributes() as $attribute) {
/** @var AttributeOption $option */
$option = $attribute->getAttributeOption();
/** @var AttributeOptionMeta $optionMeta */
$optionMeta = $option->getDomainMeta($domain);
if ($optionMeta) {
$optionValue = $option->getLongTitle($databaseTranslator);
if (!$optionValue) {
$optionValue = $option->getTitle($databaseTranslator);
}
$optionTitle = $option->getAttribute()->getTitle($databaseTranslator);
// Option Price excluding VAT
if ($useZeroVat) {
if ($optionMeta->isDiscounted()) {
$price = $optionMeta->getDomainDiscount();
$optionSpecialValue += $optionMeta->getDomainDiscount();
} else {
$price = $optionMeta->getDomainPrice();
}
$optionPriceValue += $optionMeta->getDomainPrice();
} // Option Price including VAT
else {
if ($optionMeta->isDiscounted()) {
if (isset($customer) && $customer->getId() == Customer::MAXMEDIA_KFT_ID) {
$price = $domain->createVatPrice($optionMeta->getDiscount(), 1.27);
$optionSpecialValue += $domain->createVatPrice($optionMeta->getDiscount(), 1.27);
} else {
$price = $optionMeta->getDomainVatDiscount();
$optionSpecialValue += $optionMeta->getDomainVatDiscount();
}
} else {
if (isset($customer) && $customer->getId() == Customer::MAXMEDIA_KFT_ID) {
$price = $domain->createVatPrice($optionMeta->getPrice(), 1.27);
} else {
$price = $optionMeta->getDomainVatPrice();
}
}
if (isset($customer) && $customer->getId() == Customer::MAXMEDIA_KFT_ID) {
$optionPriceValue += $domain->createVatPrice($optionMeta->getPrice(), 1.27);
} else {
$optionPriceValue += $optionMeta->getDomainVatPrice();
}
}
$optionModel = $optionHref = '';
$optionProduct = $option->getProduct();
if ($optionProduct) {
$optionModel = $optionProduct->getCode();
$optionHref = $this->url($request)->link('product', [
'product_id' => $optionProduct->getId(),
'isBazaar' => $optionProduct->isBazaar()
]);
}
// If Attribute Option is for Cross-sell
if (isset($crossSellAttributeOptions[$option->getId()])) {
if (isset($crossSellAttributeOptions[$option->getId()]['percentPrice'])) {
$price = $domain->createVatPrice((($item->getPriceWithAttributesForDomainWithException($domain, $option) * $crossSellAttributeOptions[$option->getId()]['percentPrice']) / 100), 1.);
}
}
$configurationProduct = $optionProduct ? $this->getProductHelper($request)->getStructuredDataByProductId($optionProduct->getId(), 'configurator') : null;
$options[] = [
'id' => $attribute->getId(),
'title' => $optionTitle,
'value' => $optionValue,
'price' => $price * $item->getQuantity(),
'model' => $optionModel,
'href' => $optionHref,
'image' => $configurationProduct ? $this->getImage($configurationProduct['images'], 'product/' . $optionProduct->getId())->resize(Image::PRODUCT_CART_THUMB_WIDTH, Image::PRODUCT_CART_THUMB_HEIGHT) : $this->getImage('placeholder.png', '')->resize(Image::PRODUCT_CART_THUMB_WIDTH, Image::PRODUCT_CART_THUMB_WIDTH),
];
$optionPrice += $price;
}
}
// Price
$priceValue = $specialValue = $originalPrice = 0;
if ($useZeroVat) {
if ($product['isDiscounted']) {
$price = $specialValue = $product['rawDiscountPrice'];
$originalPrice = $product['price'];
} else {
$price = $product['price'];
}
$priceValue = $product['price'];
} else {
if ($product['isDiscounted']) {
if (isset($customer) && $customer->getId() == Customer::MAXMEDIA_KFT_ID) {
$price = $specialValue = $domain->createVatPrice($product['discountPrice'], 1.27);
$originalPrice = $domain->createVatPrice($product['rawPrice'], 1.27);
} else {
$price = $specialValue = $product['discountVatPrice'];
$originalPrice = $product['vatPrice'];
}
} else {
if (isset($customer) && $customer->getId() == Customer::MAXMEDIA_KFT_ID) {
$price = $domain->createVatPrice($product['rawPrice'], 1.27);
} else {
$price = $product['vatPrice'];
}
}
if (isset($customer) && $customer->getId() == Customer::MAXMEDIA_KFT_ID) {
$priceValue = $domain->createVatPrice($product['rawPrice'], 1.27);
} else {
$priceValue = $product['vatPrice'];
}
}
// Stock
if ($itemProduct->isContainer()) {
foreach ($itemProduct->getProductContainers() as $container) {
$child = $container->getChild();
if (is_null($child)) {
continue;
}
if ($child) {
if (!$child->isAvailable()) {
$stock = false;
break;
}
if ($child->getAvailable() < ($container->getMultiplier() * $item->getQuantity())) {
$stock = false;
break;
}
}
}
} else { // Simple product
if (!$itemProduct->isAvailable()) {
$stock = false;
}
if ($itemProduct->getAvailable() < $item->getQuantity()) {
$stock = false;
}
if ($product['isReservable']) {
$stock = true;
}
}
$data['items'][] = [
'id' => $item->getId(),
'productId' => $product['id'],
'typeId' => $product['productTypeId'],
'model' => $product['code'],
'name' => ($product['vendor'] !== '' ? $product['vendor'] . ' ' : '') . $product['title'],
'description' => $product['shortDescription'],
'image' => $image,
'quantity' => $item->getQuantity(),
'originalPrice' => $product['isDiscounted'] ? ($originalPrice * $item->getQuantity()) : false,
'price' => $price * $item->getQuantity(),
'options' => $options,
'stock' => $stock,
'href' => $this->url($request)->link('product', [
'product_id' => $product['id'],
'isBazaar' => $product['isBazaar'] ?? 0
]),
];
$data['subTotal'] += ($price + $optionPrice) * $item->getQuantity();
if (!$stock) {
$data['stock'] = false;
}
$data['marketingProductsGA4'] .= ($data['marketingProductsGA4'] !== '' ? ',' : '') . '{ item_id: \'' . $product['code'] . '\', item_name: \'' . ($product['vendor'] !== '' ? $product['vendor'] . ' ' : '') . $product['title'] . '\', item_brand: \'' . $product['vendor'] . '\', item_category: \'' . $product['productType'] . '\', quantity: ' . $item->getQuantity() . ', discount: \'' . (round(($specialValue + $optionSpecialValue), $data['precision']) > 0 ? (round(($priceValue + $optionPriceValue), $data['precision']) - round(($specialValue + $optionSpecialValue), $data['precision'])) : 0) . '\', price: \'' . round(($priceValue + $optionPriceValue), $data['precision']) . '\', index: ' . $index . '}';
}
if (!$enableFreeShipping && $cart->getDomain()->getLanguage()->getCode() != 'en') {
/**
* CHECK IF EXIST A SHIPPING METHOD WITH FREE SHIPPING
*/
$shippingTypes = $entityManager->createQueryBuilder()
->select('dst')
->from('AtechNetCoreBundle:DomainShippingType', 'dst')
->where('dst.domain = :domain')
->andWhere('dst.freeShippingStartDate IS NOT NULL AND dst.freeShippingEndDate IS NOT NULL')
->andWhere('dst.freeShippingStartDate <= :now AND dst.freeShippingEndDate >= :now')
->setParameters([
'domain' => $domain->getId(),
'now' => (new \DateTime())->format('Y-m-d'),
])
->getQuery()
->getResult();
$filteredShippingTypes = array_filter($shippingTypes, function ($shippingType) use ($product) {
/** @var DomainShippingType $shippingType */
return in_array($product['productTypeId'], $shippingType->getFreeShippingProductTypes(), true);
});
$enableFreeShipping = count($filteredShippingTypes) > 0;
}
}
$data['expire'] = $expire->format('Y-m-d H:i:s');
$data['estimation'] = true;
$data['coupon'] = $data['shippingTitle'] = '';
$data['paymentCost'] = $data['shippingCost'] = $data['discount'] = 0;
$data['shippingIsSelected'] = false;
$data['domainId'] = $domainId;
$dataForLowestShippingPriceFunction = [
'domain' => $domain,
'cart' => $cart,
'subTotal' => $data['subTotal'],
'packetaCodLimit' => Packeta::getCodLimitByDomainMarketCode(strtoupper($domain->getLanguage()->getCode())),
];
$translator = $this->getTranslator();
if ($request->getSession()->has('checkout')) {
$checkout = $request->getSession()->get('checkout');
// Selected Shipping Method
if (isset($checkout['shippingMethodId']) && (int)$checkout['shippingMethodId'] > 0) {
$shippingMethod = $entityManager->getRepository(DomainShippingType::class)->findOneBy([
'id' => $checkout['shippingMethodId'],
'domain' => $domainId,
]);
if ($shippingMethod) {
// Shipping Cost
$data['shippingCost'] = $shippingMethod->getPrice();
// Free Shipping
if ((float)$shippingMethod->getFreeShipLimit() > 0 && (float)$shippingMethod->getFreeShipLimit() < $data['subTotal']) {
$data['shippingCost'] = 0;
}
if ($enableFreeShipping) {
$data['shippingCost'] = 0;
}
$data['estimation'] = false;
$data['shippingIsSelected'] = true;
}
} // Default Shipping Method
else {
$shippingMethodWithLowestPrice = CartHelper::getShippingMethodWithLowestPriceForDomain($dataForLowestShippingPriceFunction, $entityManager);
if ($shippingMethodWithLowestPrice && !$enableFreeShipping) {
// Lowest shipping Cost
$data['shippingCost'] = $shippingMethodWithLowestPrice->getPrice();
// Lowest shipping Name
$data['shippingTitle'] = str_replace("(%address%)", "", $translator->trans("shipping.method.type." . $shippingMethodWithLowestPrice->getType()));
// Free Shipping
if ((float)$shippingMethodWithLowestPrice->getFreeShipLimit() > 0 && (float)$shippingMethodWithLowestPrice->getFreeShipLimit() < $data['subTotal']) {
$data['shippingCost'] = 0;
}
$data['estimation'] = false;
}
}
$data['freeShipping'] = $enableFreeShipping;
if (isset($checkout['paymentMethodId']) && (int)$checkout['paymentMethodId'] > 0) {
$paymentMethod = $entityManager->getRepository(DomainPaymentType::class)->findOneBy([
'id' => $checkout['paymentMethodId'],
'domain' => $domainId,
]);
if ($paymentMethod) {
$data['paymentCost'] = $paymentMethod->getPrice();
}
}
if (isset($checkout['paymentMethodTypeId']) && (int)$checkout['paymentMethodTypeId'] == PaymentType::CashOnDelivery->value) {
$domainPaymentType = $entityManager->getRepository(DomainPaymentType::class)->findOneBy(
[
'domain' => $multiStore->getDomainId(),
'type' => $checkout['paymentMethodTypeId'],
]
);
if ($domainPaymentType) {
$data['cashOnDeliveryProductItem'] = [
'title' => $translator->trans('Cash on delivery'),
'price' => $domainPaymentType->getPrice(),
];
}
}
} else {
$shippingMethodWithLowestPrice = CartHelper::getShippingMethodWithLowestPriceForDomain($dataForLowestShippingPriceFunction, $entityManager);
if ($shippingMethodWithLowestPrice) {
// Shipping Cost
$data['shippingCost'] = $shippingMethodWithLowestPrice->getPrice();
// Lowest shipping Name
$data['shippingTitle'] = str_replace("(%address%)", "", $translator->trans("shipping.method.type." . $shippingMethodWithLowestPrice->getType()));
// Free Shipping
if ((float)$shippingMethodWithLowestPrice->getFreeShipLimit() > 0 && (float)$shippingMethodWithLowestPrice->getFreeShipLimit() < $data['subTotal']) {
$data['shippingCost'] = 0;
}
$data['estimation'] = false;
}
}
// Coupon
if (isset($checkout['coupon']['code']) && $checkout['coupon']['code'] != '') {
$data['coupon'] = $checkout['coupon']['code'];
$coupon = $entityManager->getRepository(Coupon::class)->findOneBy([
'code' => $checkout['coupon']['code'],
'domain' => $domain,
]);
if ($coupon) {
// Set Email
if (!empty($checkout['email'])) {
$cart->setEmail($checkout['email']);
} else {
$cart->setEmail(null);
}
// Coupon Free Shipping
$isCouponApplicableForFreeShipping = CartHelper::isCouponApplicableForFreeShipping($coupon, $cart, $entityManager);
// Coupon Discount
$isCouponValidForBasket = CartHelper::isCouponValidForBasket($coupon, $cart, $entityManager);
if ($isCouponValidForBasket !== false || $isCouponApplicableForFreeShipping) {
$data['discount'] = (float)$isCouponValidForBasket;
} else {
$data['coupon'] = '';
}
// Free Shipping
if ($isCouponApplicableForFreeShipping) {
$data['shippingCost'] = 0;
}
} else {
$data['coupon'] = '';
}
}
if (isset($checkout['3_percent_discount']) && $checkout['3_percent_discount'] && $data['discount'] == 0) {
if ($cart) {
$data['discount'] = CartHelper::getPercentDiscountForBasket($cart, 3);
$data['three_percent_partner_discount'] = true;
}
}
$shippingCost = $data['shippingIsSelected'] ? $data['shippingCost'] : 0;
$data['total'] = $data['subTotal'] + $shippingCost + $data['paymentCost'] - $data['discount'];
$data['currency_ISO'] = $this->getCurrencyISOForm($domain->getCurrency());
return $this->render('AtechNetCoreBundle/Checkout/cart.html.twig', $data);
}
/**
* @var Request $request
* @var int|null $customerId
*/
private function checkCustomerLoginStatusForAbandonedCart(Request $request, ?object $abandonedCartObject)
{
$translator = $this->getTranslator();
/**
* @var Customer $loggedInCustomer
*/
$loggedInCustomer = $this->getLoginHelper($request)->getLoggedInCustomer();
if (!$abandonedCartObject->customerId) {
if ($loggedInCustomer) {
return [
'alertText' => $translator->trans('Another profile (with another email) is signed in. You have to log out first to continue abandoned cart ordering.'),
];
}
return null;
}
$customerId = $abandonedCartObject->customerId;
$entityManager = $this->getEntityManager();
/**
* @var Customer $customer
*/
$customer = $entityManager->getRepository(Customer::class)->findOneById($customerId);
if ($customer->isGuest()) {
if ($loggedInCustomer) {
return [
'alertText' => $translator->trans('Another profile (with another email) is signed in. You have to log out first to continue abandoned cart ordering.'),
];
}
return null;
}
if (!$loggedInCustomer) {
return 'redirectToLogin';
}
if ($loggedInCustomer->getId() != $customer->getId()) {
return [
'signInRequired' => true,
'alertText' => $translator->trans('Another profile (with another email) is signed in. You have to log out AND log in with your <b>{emailToLogIn}</b> email to continue abandoned cart ordering.', [
'{emailToLogIn}' => $abandonedCartObject->email,
]),
];
}
}
/**
* @Route("/cart/add", name="cart_add", defaults={"_locale":""})
* @Route("/{_locale<%supported_locales%>?}/cart/add", name="cart_add_locale", defaults={"_locale":""})
* @param Request $request
* @return JsonResponse
*/
public function addAction(Request $request)
{
$json = [];
$translator = $this->getTranslator();
$databaseTranslator = $this->getDatabaseTranslator($request);
$entityManager = $this->getEntityManager();
$productId = $request->request->get('product_id');
/**
* @var Product $product
*/
$product = $entityManager->getRepository(Product::class)->findOneById($productId);
if (!$product) {
$json['error'] = $this->renderView(
'AtechNetCoreBundle/Common/modal.html.twig',
[
'type' => 'error',
'message' => $translator->trans('Product not found'),
]
);
return new JsonResponse($json);
}
$multiStore = $this->getMultiStoreHelper($request);
$productHelper = $this->getProductHelper($request);
$domain = $multiStore->getDomain();
$currency = $domain->getCurrency();
$precision = $domain->getPricePrecision();
$customer = $this->getLoginHelper($request)->getLoggedInCustomer();
$useZeroVat = $this->useZeroVat($customer, $request);
$cart = $this->getCart($request->getSession()->get('cartId'));
if (!$cart) {
$cart = new Basket();
$cart->setDomain($domain);
$cart->setPaymentMethod(0);
$cart->setShippingMethod(0);
$cart->setUseBillingAddressAsShippingAddress(false);
$cart->setMessage('');
$entityManager->persist($cart);
$entityManager->flush();
$request->getSession()->set('cartId', $cart->getId());
}
if (is_null($cart->getCustomer())) {
$loggedInCustomer = $this->getLoginHelper($request)->getLoggedInCustomer();
if ($loggedInCustomer) {
$cart->setCustomer($loggedInCustomer);
}
}
// Stock items
$stockItems = $request->request->get('stockItems');
// Quantity
$quantity = $request->request->get('quantity') ?? 1;
if ($stockItems) {
$quantity = count($stockItems);
$stockItemCodes = $request->getSession()->get('stockItemCodes');
$stockItemCodes[$productId] = $stockItems;
$request->getSession()->set('stockItemCodes', $stockItemCodes);
}
$options = [];
if (!is_null($request->request->get('option'))) {
// Options
$options = $request->request->get('option');
// Remove unwanted options
foreach ($options as $key => $optionId) {
if (in_array($optionId, $this->unWantedAttributes)) {
unset($options[$key]);
}
}
}
if (in_array($product->getType()->getId(), [
ProductType::PRODUCT_TYPE_ID_PC,
ProductType::PRODUCT_TYPE_ID_NOTEBOOK,
ProductType::PRODUCT_TYPE_ID_ALL_IN_ONE,
ProductType::PRODUCT_TYPE_ID_PHONE,
ProductType::PRODUCT_TYPE_ID_SMARTPHONE,
ProductType::PRODUCT_TYPE_ID_TABLET,
ProductType::PRODUCT_TYPE_ID_PC_SET,
]) && in_array($domain->getId(), MultiStore::getRetailDomainIDs()))
{
if (!isset($options[Attribute::ATTRIBUTE_ID_ACCESSORY_ANTIVIRUS_SOFTWARE]) || $options[Attribute::ATTRIBUTE_ID_ACCESSORY_ANTIVIRUS_SOFTWARE] == "")
{
$options[Attribute::ATTRIBUTE_ID_ACCESSORY_ANTIVIRUS_SOFTWARE] = AttributeOption::ATTRIBUTE_OPTION_ID_NORTON_ANTIVIRUS_FREE;
}
}
$noWebcam = (new ArrayCollection($product->getSpecificationAttributeOptions(false)))->filter(function (AttributeOption $ao) {
return $ao->getId() == AttributeOption::ATTRIBUTE_OPTION_NO_WEBCAM;
})->first();
if ($product->getType()->getId() == ProductType::PRODUCT_TYPE_ID_NOTEBOOK && $noWebcam) {
$freeWebcamAcc = $entityManager->getRepository(AttributeOption::class)->findOneBy(['id' => AttributeOption::ATTRIBUTE_OPTION_ID_NO_WEBCAM_FREE_WEBCAM]);
if (!$freeWebcamAcc->getProduct()?->isAvailable() && $freeWebcamAcc->getProduct()?->getCode() == 2040025 /*ez az olcsobbik*/) {
$newFreeWebcam = $entityManager->getRepository(Product::class)->findOneBy(['code' => 2040005]);
$freeWebcamAcc->setProduct($newFreeWebcam);
$entityManager->flush();
$entityManager->refresh($freeWebcamAcc);
}
if (!isset($options[Attribute::ATTRIBUTE_ID_ACCESSORY_FREE_WEBCAM]) || $options[Attribute::ATTRIBUTE_ID_ACCESSORY_FREE_WEBCAM] == "")
{
$options[Attribute::ATTRIBUTE_ID_ACCESSORY_FREE_WEBCAM] = AttributeOption::ATTRIBUTE_OPTION_ID_NO_WEBCAM_FREE_WEBCAM;
}
}
// Check if item is already in cart
$exists = false;
$reachedLimit = false;
/** @var BasketItem $item */
foreach ($cart->getBasketItems() as $item) {
if ($product->getId() == $item->getProduct()->getId()) {
$exists = $item->getId();
$quantity = $stockItems ? count($stockItems) : $item->getQuantity() + 1;
if (!is_null($item->getProduct()->getQuantityLimit()) && $quantity > $item->getProduct()->getQuantityLimit()) {
$reachedLimit = true;
}
break;
}
}
$stock = true;
$available = true;
if (!$product->isAvailable()) {
$stock = false;
}
if ($product->getAvailable() < $quantity && $product->getOutOfStockStatus() !== Product::OutOfStockStatus_VisibleShadow) {
$stock = false;
}
if ($product->isReservable()) {
$stock = true;
}
$meta = $product->getDomainMeta($domain);
if ($meta) {
if (!$meta->isOrderable()) {
$available = false;
}
if ($product->isReservable() && $meta->isReady() && $meta->isActive()) {
$available = true;
}
} else {
$available = false;
}
if (!$available) {
$json['error'] = $this->renderView(
'AtechNetCoreBundle/Common/modal.html.twig',
[
'type' => 'add-to-cart-warning',
'message' => $translator->trans('Unfortunately, the product {product} is currently unavailable', [
'product' => $product->getName(),
]),
]
);
} elseif (!$stock) {
$json['error'] = $this->renderView(
'AtechNetCoreBundle/Common/modal.html.twig',
[
'type' => 'add-to-cart-warning',
'message' => $translator->trans('Unfortunately, the product {product} is not available in the desired quantity or not in stock', [
'product' => $product->getName(),
]),
]
);
} elseif ($reachedLimit) {
$json['error'] = $this->renderView(
'AtechNetCoreBundle/Common/modal.html.twig',
[
'type' => 'add-to-cart-warning',
'message' => $translator->trans('Unfortunately, the product {product} has an order quantity limit', [
'product' => $product->getName(),
]),
]
);
} else {
if ($exists === false) {
$item = new BasketItem();
$item->setBasket($cart);
$item->setProduct($product);
$item->setQuantity($quantity);
$cart->addBasketItem($item);
$cart->setUpdated(new \DateTime());
$entityManager->flush();
foreach ($options as $optionId) {
$option = $entityManager->getRepository(AttributeOption::class)->findOneById($optionId);
if ($option) {
$attributeOption = new BasketItemAttributeOption();
$attributeOption->setBasketItem($item);
$attributeOption->setAttributeOption($option);
$entityManager->persist($attributeOption);
$entityManager->flush();
$entityManager->refresh($item);
}
}
} else {
$item = $entityManager->getRepository(BasketItem::class)->findOneById($exists);
$item->setQuantity($quantity);
$cart->setUpdated(new \DateTime());
$entityManager->flush();
}
$itemProduct = $item->getProduct();
$productData = $productHelper->getStructuredDataForProduct($itemProduct, 'cart');
// Image
$image = $this->getImage('placeholder.jpg', '')->resize(Image::PRODUCT_VIEW_ADDITIONAL_WIDTH, Image::PRODUCT_VIEW_ADDITIONAL_HEIGHT);
if (is_object($productData['images'])) {
$image = $this->getImage($productData['images'], 'product/' . $productData['code'])->resize(Image::PRODUCT_VIEW_ADDITIONAL_WIDTH, Image::PRODUCT_VIEW_ADDITIONAL_HEIGHT);
}
// Price
$specialValue = 0;
if ($useZeroVat) {
if ($productData['isDiscounted']) {
$price = $specialValue = $productData['rawDiscountPrice'];
} else {
$price = $productData['price'];
}
$priceValue = $productData['price'];
} else {
if ($productData['isDiscounted']) {
$price = $specialValue = $productData['discountVatPrice'];
} else {
$price = $productData['vatPrice'];
}
$priceValue = $productData['vatPrice'];
}
// Option Price
$optionPrice = $optionPriceValue = $optionSpecialValue = 0;
$attributeOptions = [];
if ($item->getItemAttributes()) {
foreach ($item->getItemAttributes() as $attribute) {
$option = $attribute->getAttributeOption();
$optionMeta = $option->getDomainMeta($domain);
if ($optionMeta) {
// Option Price excluding VAT
if ($useZeroVat) {
if ($optionMeta->isDiscounted()) {
$optionSpecialValue += $optionMeta->getDomainDiscount();
}
$optionPriceValue += $optionMeta->getDomainPrice();
} // Option Price including VAT
else {
if ($optionMeta->isDiscounted()) {
$optionSpecialValue += $optionMeta->getDomainVatDiscount();
}
$optionPriceValue += $optionMeta->getDomainVatPrice();
}
}
$attributeOptions[] = $option->getId();
}
}
// Cross-sell Attribute Options
$selectedCrossSellAttributeIds = [];
$crossSellAttributeOptionsData = [];
$crossSellAttributeOptions = CartHelper::getCrossSellAttributeOptionsByProductTypeId($productData['productTypeId'], $domain->getId());
if (!empty($crossSellAttributeOptions)) {
$crossSellAttributeOptionsData = [];
foreach ($crossSellAttributeOptions as $attributeOptionId => $optionData) {
$attributeOption = $entityManager->getRepository(AttributeOption::class)->findOneById($attributeOptionId);
if ($attributeOption) {
$attributeOptionPrice = false;
if (isset($optionData['percentPrice'])) {
$attributeOptionPrice = $domain->createVatPrice((($item->getPriceWithAttributesForDomainWithException($domain, $attributeOption) * $optionData['percentPrice']) / 100), 1.);
} else {
$attributeOptionMeta = $attributeOption->getDomainMeta($domain);
if ($attributeOptionMeta) {
// Option Price excluding VAT
if ($useZeroVat) {
if ($attributeOptionMeta->isDiscounted()) {
$attributeOptionPrice = $attributeOptionMeta->getDomainDiscount();
} else {
$attributeOptionPrice = $attributeOptionMeta->getDomainPrice();
}
} // Option Price including VAT
else {
if ($attributeOptionMeta->isDiscounted()) {
$attributeOptionPrice = $attributeOptionMeta->getDomainVatDiscount();
} else {
$attributeOptionPrice = $attributeOptionMeta->getDomainVatPrice();
}
}
}
}
$crossSellAttributeOptionImage = false;
if (isset($optionData['image'])) {
$crossSellAttributeOptionImage = $optionData['image'];
} else {
$attributeOptionProduct = $attributeOption->getProduct();
if ($attributeOptionProduct) {
if ($attributeOptionProduct->getAlbum()->getPhotos()) {
$crossSellAttributeOptionImage = $this->getImage($attributeOptionProduct->getAlbum()->getPhotos()->first(), 'product/' . $attributeOptionProduct->getCode())->resize(Image::PRODUCT_CART_THUMB_WIDTH, Image::PRODUCT_CART_THUMB_HEIGHT);
}
}
}
$crossSellAttributeOptionsData[] = [
'attributeOptionId' => $attributeOptionId,
'attributeId' => $attributeOption->getAttribute()->getId(),
'image' => $crossSellAttributeOptionImage,
'name' => $databaseTranslator->trans($attributeOption->getTitle()),
'additionalInfo' => isset($optionData['additionalInfo']) ? $translator->trans($optionData['additionalInfo']) : false,
'price' => $attributeOptionPrice ? number_format($attributeOptionPrice, $precision, ',', ' ') . ' ' . $currency : false,
];
if (in_array($attributeOption->getId(), $attributeOptions)) {
$selectedCrossSellAttributeIds[$attributeOption->getAttribute()->getId()] = $attributeOption->getId();
}
}
}
}
$json['crossSellAttributeOptionsData'] = $crossSellAttributeOptionsData;
$currency = $domain->getCurrency();
$currency_ISO = $this->getCurrencyISOForm($currency);
$json['success'] = [
'data' => [
'value' => [
'price' => round(($priceValue + ($optionPriceValue + $optionSpecialValue)), $precision),
'special' => round(($specialValue + ($optionPriceValue + $optionSpecialValue)), $precision),
],
'quantity' => $quantity,
'code' => $productData['code'],
'name' => $productData['title'],
'brand' => $productData['vendor'],
'productType' => $productData['productType'],
],
'html' => $this->renderView(
'AtechNetCoreBundle/Common/modal.html.twig',
[
'type' => 'add-to-cart-success',
'productId' => $itemProduct->getId(),
'quantity' => $quantity,
'code' => $productData['code'],
'name' => $productData['title'],
'brand' => $productData['vendor'],
'image' => $image,
'currency_ISO' => $currency_ISO,
'productType' => $productData['productType'],
'price' => number_format((($price + $optionPriceValue) * $quantity), $precision, ',', ' ') . ' ' . $currency,
'value' => [
'price' => round(($priceValue + $optionPriceValue), $precision),
'special' => round(($specialValue + $optionSpecialValue), $precision),
],
'zeroVat' => $useZeroVat,
'selectedCrossSellAttributeIds' => $selectedCrossSellAttributeIds,
'crossSellOptions' => $crossSellAttributeOptionsData,
'qualityStatusId' => $productData['qualityStatusId'],
]
),
];
// Gift - Pexeso
if (
Product::PEXESO_SCHOOL_GIFT_ITEM_ID > 0
&& in_array($domain->getId(), [ Domain::DOMAIN_ID_RT_SK, Domain::DOMAIN_ID_RT_CZ, Domain::DOMAIN_ID_RT_HU, Domain::DOMAIN_ID_RT_EU ])
&& $product->getType()?->getId() == ProductType::PRODUCT_TYPE_ID_NOTEBOOK
&& $meta->isDiscounted() && $meta->isDiscountValid()
) {
$giftBasketItem = null;
/** @var BasketItem $basketItem */
foreach ( $cart->getBasketItems() as $basketItem ) {
if ( $basketItem->getProduct()->getId() == Product::PEXESO_SCHOOL_GIFT_ITEM_ID ) {
$giftBasketItem = $basketItem;
break;
}
}
if ( is_null($giftBasketItem) ) {
$giftProduct = $entityManager->getRepository(Product::class)->find(Product::PEXESO_SCHOOL_GIFT_ITEM_ID);
if ( $giftProduct && $giftProduct->getAvailable() > 0 ) {
$basketItem = new BasketItem();
$basketItem->setBasket($cart);
$basketItem->setProduct($giftProduct);
$basketItem->setQuantity(1);
$entityManager->persist($basketItem);
$entityManager->flush();
}
}
}
}
return new JsonResponse($json);
}
/**
* @Route("/cart/update", name="cart_update", defaults={"_locale":""})
* @Route("/{_locale<%supported_locales%>?}/cart/update", name="cart_update_locale", defaults={"_locale":""})
* @param Request $request
* @return JsonResponse
* @throws \Exception
*/
public function updateAction(Request $request)
{
$json = [];
$cart = $this->getCart($request->getSession()->get('cartId'));
if ($cart) {
$entityManager = $this->getEntityManager();
$multiStore = $this->getMultiStoreHelper($request);
$productHelper = $this->getProductHelper($request);
$domain = $multiStore->getDomain();
$currency = $domain->getCurrency();
$precision = $domain->getPricePrecision();
$itemId = (int)$request->request->get('item');
$itemAttributeId = (int)$request->request->get('option');
$quantity = (int)$request->request->get('quantity');
$customer = $this->getLoginHelper($request)->getLoggedInCustomer();
$useZeroVat = $this->useZeroVat($customer, $request);
if ($quantity > 0) {
$json['product'] = [
'id' => $itemId,
'quantity' => 0,
'price' => 0,
'originalPrice' => 0,
'options' => [],
];
$json['stock'] = [];
$json['total'] = 0;
$json['subTotal'] = 0;
foreach ($cart->getBasketItems() as $item) {
$product = $productHelper->getStructuredDataForProduct($item->getProduct(), 'cart');
if ($product) {
// Update quantity
if ((int)$item->getId() == $itemId) {
if (!is_null($item->getProduct()->getQuantityLimit()) && $quantity > $item->getProduct()->getQuantityLimit()) {
$json['error'][] = $item->getId();
return new JsonResponse($json);
}
$item->setQuantity($quantity);
$originalPrice = 0;
if ($useZeroVat) {
if ($product['isDiscounted']) {
$price = $product['discountPrice'];
$originalPrice = $product['price'];
} else {
$price = $product['price'];
}
} else {
if ($product['isDiscounted']) {
$price = $product['discountVatPrice'];
$originalPrice = $product['vatPrice'];
} else {
$price = $product['vatPrice'];
}
}
$json['product']['quantity'] = $item->getQuantity();
$json['product']['price'] = number_format(($price * $item->getQuantity()), $precision, ',', ' ') . ' ' . $currency;
if ($originalPrice > 0) {
$json['product']['originalPrice'] = number_format(($originalPrice * $item->getQuantity()), $precision, ',', ' ') . ' ' . $currency;
}
}
// Cross-sell Attribute Options
$crossSellAttributeOptions = CartHelper::getCrossSellAttributeOptionsByProductTypeId($product['productTypeId'], $domain->getId());
$optionPrice = 0;
foreach ($item->getItemAttributes() as $attribute) {
$option = $attribute->getAttributeOption();
$optionMeta = $option->getDomainMeta($domain);
if ($optionMeta) {
// Option Price excluding VAT
if ($useZeroVat) {
if ($optionMeta->isDiscounted()) {
$price = $optionMeta->getDomainDiscount();
} else {
$price = $optionMeta->getDomainPrice();
}
} // Option Price including VAT
else {
if ($optionMeta->isDiscounted()) {
$price = $optionMeta->getDomainVatDiscount();
} else {
$price = $optionMeta->getDomainVatPrice();
}
}
// Cross-sell Attribute Options Calculated Price
if (isset($crossSellAttributeOptions[$option->getId()])) {
if (isset($crossSellAttributeOptions[$option->getId()]['percentPrice'])) {
$price = $domain->createVatPrice((($item->getPriceWithAttributesForDomainWithException($domain, $option) * $crossSellAttributeOptions[$option->getId()]['percentPrice']) / 100), 1.);
}
}
$json['product']['options'][] = [
'id' => $attribute->getId(),
'price' => ($price > 0 ? number_format(($price * $item->getQuantity()), $precision, ',', ' ') . ' ' . $currency : ''),
];
$optionPrice += $price;
}
}
if ($useZeroVat) {
$price = $product['isDiscounted'] ? $product['discountPrice'] : $product['price'];
} else {
$price = $product['isDiscounted'] ? $product['discountVatPrice'] : $product['vatPrice'];
}
$json['subTotal'] += ($price + $optionPrice) * $item->getQuantity();
}
}
$paymentCost = $shippingCost = $json['discount'] = 0;
if ($request->getSession()->has('checkout')) {
$checkout = $request->getSession()->get('checkout');
if (isset($checkout['shippingMethodId']) && (int)$checkout['shippingMethodId'] > 0) {
$shippingMethod = $entityManager->getRepository(DomainShippingType::class)->findOneBy([
'id' => $checkout['shippingMethodId'],
'domain' => $multiStore->getDomainId(),
]);
if ($shippingMethod) {
// Shipping Cost
$shippingCost = $shippingMethod->getPrice();
// Free Shipping
if ((float)$shippingMethod->getFreeShipLimit() > 0 && (float)$shippingMethod->getFreeShipLimit() < $json['subTotal']) {
$shippingCost = 0;
}
}
}
if (isset($checkout['paymentMethodId']) && (int)$checkout['paymentMethodId'] > 0) {
$paymentMethod = $entityManager->getRepository(DomainPaymentType::class)->findOneBy([
'id' => $checkout['paymentMethodId'],
'domain' => $multiStore->getDomainId(),
]);
if ($paymentMethod) {
$paymentCost = $paymentMethod->getPrice();
}
}
if (isset($checkout['coupon']['code']) && $checkout['coupon']['code'] != '') {
$coupon = $paymentMethod = $entityManager->getRepository(Coupon::class)->findOneBy([
'code' => $checkout['coupon']['code'],
'domain' => $domain,
]);
if ($coupon) {
// Set Email
if (!empty($checkout['email'])) {
$cart->setEmail($checkout['email']);
} else {
$cart->setEmail(null);
}
$isCouponValidForBasket = CartHelper::isCouponValidForBasket($coupon, $cart, $entityManager);
if ($isCouponValidForBasket) {
$json['discount'] = $isCouponValidForBasket;
}
// Coupon Free Shipping
$isCouponApplicableForFreeShipping = CartHelper::isCouponApplicableForFreeShipping($coupon, $cart, $entityManager);
if ($isCouponApplicableForFreeShipping) {
$shippingCost = 0;
}
}
}
}
$json['total'] = number_format(($json['subTotal'] + $shippingCost + $paymentCost - $json['discount']), $precision, ',', ' ') . ' ' . $currency;
$json['subTotal'] = number_format($json['subTotal'], $precision, ',', ' ') . ' ' . $currency;
if ((float)$json['discount'] > 0) {
$json['discount'] = number_format($json['discount'], $precision, ',', ' ') . ' ' . $currency;
} else {
$json['discount'] = '';
}
$entityManager->refresh($cart);
$entityManager->flush();
// // Validate product availability
foreach ($cart->getBasketItems() as $item) {
$product = $item->getProduct();
if ($product) {
if ($product->isContainer()) { // Container
foreach ($product->getProductContainers() as $container) {
$child = $container->getChild();
if (is_null($child)) {
continue;
}
if ($child) {
if (!$child->isAvailable()) {
$json['stock'][] = $item->getId();
break;
}
if ($child->getAvailable() < ($container->getMultiplier() * $item->getQuantity()) && $child->getOutOfStockStatus() !== Product::OutOfStockStatus_VisibleShadow) {
$json['stock'][] = $item->getId();
break;
}
}
}
} else { // Simple product
if (!$product->isAvailable()) {
$json['stock'][] = $item->getId();
}
if ($product->getAvailable() < $item->getQuantity() && $product->getOutOfStockStatus() !== Product::OutOfStockStatus_VisibleShadow) {
$json['stock'][] = $item->getId();
}
}
}
}
} else {
$json['redirect'] = $this->generateUrl('cart_show');
if ($itemAttributeId > 0) {
foreach ($cart->getBasketItems() as $item) {
if ((int)$item->getId() == $itemId) {
foreach ($item->getItemAttributes() as $attribute) {
if ((int)$attribute->getId() == $itemAttributeId) {
$item->getItemAttributes()->removeElement($attribute);
break;
}
}
break;
}
}
} else {
foreach ($cart->getBasketItems() as $item) {
if ((int)$item->getId() == $itemId) {
$cart->getBasketItems()->removeElement($item);
break;
}
}
}
$entityManager->flush();
// Gift - Pexeso
if ( $this->removeGift(Product::PEXESO_SCHOOL_GIFT_ITEM_ID, $cart, $domain) ) {
$entityManager->refresh($cart);
}
}
$cart->setUpdated((new \DateTime('NOW')));
$entityManager->flush();
} else {
$json['redirect'] = $this->generateUrl('homepage');
}
return new JsonResponse($json);
}
/**
* @Route("/cart/remove", name="cart_remove", defaults={"_locale":""})
* @Route("/{_locale<%supported_locales%>?}/cart/remove", name="cart_remove_locale", defaults={"_locale":""})
* @param Request $request
* @return JsonResponse
*/
public function removeAction(Request $request)
{
$json = [];
$entityManager = $this->getEntityManager();
$productHelper = $this->getProductHelper($request);
$customer = $this->getLoginHelper($request)->getLoggedInCustomer();
$useZeroVat = $this->useZeroVat($customer, $request);
$domain = $this->getMultiStoreHelper($request)->getDomain();
$cart = $this->getCart($request->getSession()->get('cartId'));
$stockItemCodes = $request->getSession()->get('stockItemCodes');
$productId = (int)$request->request->get('productId');
if ($cart) {
$itemId = (int)$request->request->get('item');
$itemAttributeId = (int)$request->request->get('option');
if ($itemAttributeId > 0) {
foreach ($cart->getBasketItems() as $item) {
if ((int)$item->getId() == $itemId) {
foreach ($item->getItemAttributes() as $attribute) {
if ((int)$attribute->getId() == $itemAttributeId) {
$entityManager->remove($attribute);
$item->getItemAttributes()->removeElement($attribute);
break;
}
}
break;
}
}
} else {
$json['product'] = [];
foreach ($cart->getBasketItems() as $index => $item) {
if ((int)$item->getId() == $itemId) {
$itemProduct = $item->getProduct();
$productData = $productHelper->getStructuredDataForProduct($itemProduct, 'cart');
// Price
$specialValue = 0;
if ($useZeroVat) {
$priceValue = $productData['price'];
} else {
$priceValue = $productData['vatPrice'];
}
// Option Price
$optionPriceValue = $optionSpecialValue = 0;
if ($item->getItemAttributes()) {
foreach ($item->getItemAttributes() as $attribute) {
$option = $attribute->getAttributeOption();
$optionMeta = $option->getDomainMeta($domain);
if ($optionMeta) {
// Option Price excluding VAT
if ($useZeroVat) {
if ($optionMeta->isDiscounted()) {
$optionSpecialValue += $optionMeta->getDomainDiscount();
}
$optionPriceValue += $optionMeta->getDomainPrice();
} // Option Price including VAT
else {
if ($optionMeta->isDiscounted()) {
$optionSpecialValue += $optionMeta->getDomainVatDiscount();
}
$optionPriceValue += $optionMeta->getDomainVatPrice();
}
}
}
}
$currency = $cart->getDomain()->getCurrency();
$currency_ISO = $this->getCurrencyISOForm($currency);
$precision = $cart->getDomain()->getPricePrecision();
$json['product'] = [
'currency' => $currency_ISO,
'code' => $productData['code'],
'title' => ($productData['vendor'] != '' ? $productData['vendor'] . ' ' : '') . $productData['title'],
'brand' => $productData['vendor'],
'quantity' => $item->getQuantity(),
'productType' => $productData['productType'],
'index' => $index,
'price' => round(($priceValue + $optionPriceValue), $precision),
'special' => round(($specialValue + $optionSpecialValue), $precision),
];
$entityManager->remove($item);
break;
}
}
if ($this->getEnvironment() != 'prod') {
unset($json['product']);
}
}
$cart->setUpdated((new \DateTime('NOW')));
} else {
$json['redirect'] = '';
}
$entityManager->flush();
unset($stockItemCodes[$productId]);
$request->getSession()->set('stockItemCodes', $stockItemCodes);
// Gift - Pexeso
if ( $this->removeGift(Product::PEXESO_SCHOOL_GIFT_ITEM_ID, $cart, $domain) ) {
$entityManager->refresh($cart);
}
if ($cart && $cart->getBasketItems()->count() == 1) {
/** @var BasketItem $basketItem */
$basketItem = $cart->getBasketItems()->first();
if ( $basketItem->getProduct()->getId() == Product::SUMMER_2026_COUPON_GIFT_ITEM_ID ) {
$entityManager->remove($basketItem);
$entityManager->flush();
}
}
if ($cart && count($cart->getBasketItems()) == 0) {
if ($cart->getCustomer()) {
$this->getKlaviyoConnect($request)->createBasketIsEmptiedEvent($cart->getCustomer());
}
else if ($request->getSession()->has('checkout') && isset($request->getSession()->get('checkout')['email'])) {
$checkout = $request->getSession()->get('checkout');
if (isset($checkout['email'])) {
$this->getKlaviyoConnect($request)->createBasketIsEmptiedEvent($checkout['email']);
$request->getSession()->set('customerEmailForKlaviyo', $checkout['email']);
$request->getSession()->remove('checkout');
}
}
else if ($request->getSession()->has('customerEmailForKlaviyo')) {
$this->getKlaviyoConnect($request)->createBasketIsEmptiedEvent($request->getSession()->get('customerEmailForKlaviyo'));
}
$request->getSession()->remove('checkout');
$request->getSession()->remove('stockItemCodes');
}
return new JsonResponse($json);
}
/**
* @Route("/cart/stock-item-remove", name="product_stock_item_remove", defaults={"_locale":""})
* @Route("/{_locale<%supported_locales%>?}/cart/stock-item-remove", name="product_stock_item_remove_locale", defaults={"_locale":""})
* @param Request $request
* @return JsonResponse
*/
public function stockItemRemoveAjaxAction(Request $request): JsonResponse
{
$productId = $request->get('productId');
$stockItemCode = $request->get('stockItemCode');
$stockItemCodes = $request->getSession()->get('stockItemCodes');
foreach ($stockItemCodes[$productId] as $key => $aikenCode) {
if ($stockItemCode == $aikenCode) {
unset($stockItemCodes[$productId][$key]);
if (count($stockItemCodes[$productId]) == 0) {
unset($stockItemCodes[$productId]);
}
if (count($stockItemCodes) == 0) {
$request->getSession()->remove('stockItemCodes');
}
break;
}
}
$entityManager = $this->getEntityManager();
$basketItemId = $request->get('basketItemId');
$basketItem = $entityManager->getRepository(BasketItem::class)->findOneById($basketItemId);
if ($basketItem->getQuantity() > 1) {
$basketItem->setQuantity($basketItem->getQuantity() - 1);
} else {
$basketItem->getBasket()->getBasketItems()->removeElement($basketItem);
}
$entityManager->flush();
if (count($stockItemCodes) > 0) {
$request->getSession()->set('stockItemCodes', $stockItemCodes);
}
return new JsonResponse([
'status' => 'succes',
]);
}
/**
* @Route("/cart/undo_removed", name="cart_remove_last_removed", defaults={"_locale":""})
* @Route("/{_locale<%supported_locales%>?}/cart/undo_removed", name="cart_remove_last_removed_locale", defaults={"_locale":""})
* @param Request $request
* @return JsonResponse
*/
public function emptyLastRemovedArrayAction(Request $request)
{
$productId = $request->request->get('product_id');
$product = $this->getEntityManager()->getRepository(Product::class)->findOneById($productId);
$productHelper = $this->getProductHelper($request);
$productData = $productHelper->getStructuredDataForProduct($product, 'cart');
$customer = $this->getLoginHelper($request)->getLoggedInCustomer();
$useZeroVat = $this->useZeroVat($customer, $request);
if ($useZeroVat) {
$price = $productData['isDiscounted'] ? $productData['discountPrice'] : $productData['price'];
} else {
$price = $productData['isDiscounted'] ? $productData['discountVatPrice'] : $productData['vatPrice'];
}
$dataForGtagAddItems = [
'brand' => $productData['vendor'],
'title' => $product->getName(),
'type' => $product->getType()->getTitle(),
'price' => $price,
];
$translator = $this->getTranslator();
return new JsonResponse([
'success' => $request->getSession()->remove('lastRemovedCartItem'),
'gtag' => $dataForGtagAddItems,
'error' => $this->renderView(
'AtechNetCoreBundle/Common/modal.html.twig',
[
'type' => 'error',
'message' => $translator->trans('Product not found'),
]
),
]);
}
/**
* @Route("/cart/clear-removed", name="cart_clear_removed_array", defaults={"_locale":""})
* @Route("/{_locale<%supported_locales%>?}/cart/clear-removed", name="cart_clear_removed_array_locale", defaults={"_locale":""})
* @param Request $request
* @return JsonResponse
*/
public function clearRemovedArrayAction(Request $request)
{
$request->getSession()->remove('lastRemovedCartItem');
return new JsonResponse([]);
}
/**
* @Route("/cart/coupon", name="cart_coupon", defaults={"_locale":""})
* @Route("/{_locale<%supported_locales%>?}/cart/coupon", name="cart_coupon_locale", defaults={"_locale":""})
* @param Request $request
* @return JsonResponse
*/
public function couponAction(Request $request): JsonResponse
{
$json = [];
$translator = $this->getTranslator();
if (empty($request->request->get('coupon'))) {
$json['error'] = $translator->trans('Please enter a coupon code');
return new JsonResponse($json);
}
$entityManager = $this->getEntityManager();
$basket = null;
if ($request->getSession()->has('cartId')) {
$basketId = $request->getSession()->get('cartId');
$basket = $this->getCart($basketId);
}
$couponCode = $request->request->get('coupon');
$multiStore = $this->getMultiStoreHelper($request);
$domain = $multiStore->getDomain();
$coupon = $entityManager->getRepository(Coupon::class)->createQueryBuilder('c')
->where('c.code = :code')
->andWhere('c.domain = :domain')
->andWhere('c.description NOT LIKE :description')
->setParameters([
'code' => $couponCode,
'domain' => $domain,
'description' => '%Unas%'
])->getQuery()->getOneOrNullResult();
$checkout = $request->getSession()->get('checkout') ?? [];
if (!$coupon || !$basket) {
if (in_array($couponCode, $this->getWhiteListCouponCodes()) && $basket) {
// Apply Coupon
$checkout['coupon'] = [
'code' => $couponCode,
'type' => 0,
'discount' => 0,
];
if ($basket) {
$basket->setCouponCode($couponCode);
$entityManager->flush();
}
// Save
$request->getSession()->set('checkout', $checkout);
// Alert
$json['error'] = $translator->trans('Your coupon discount has been applied');
} else {
$json['error'] = $translator->trans('Coupon is invalid');
}
return new JsonResponse($json);
}
// Validate Date
$now = (new \DateTime('now'))->getTimestamp();
if (!is_null($coupon->getValidFrom()) && $coupon->getValidFrom()->getTimestamp() > $now) {
$json['error'] = $translator->trans('Coupon is expired');
return new JsonResponse($json);
}
if (!is_null($coupon->getValidTo()) && $coupon->getValidTo()->getTimestamp() < $now) {
$json['error'] = $translator->trans('Coupon is expired');
return new JsonResponse($json);
}
$basket->setEmail(!empty($checkout['email']) ? $checkout['email'] : null);
// Coupon Free Shipping
$isCouponApplicableForFreeShipping = CartHelper::isCouponApplicableForFreeShipping($coupon, $basket, $entityManager);
// Coupon Discount
$isCouponValidForBasket = CartHelper::isCouponValidForBasket($coupon, $basket, $entityManager);
if ($isCouponValidForBasket !== false || $isCouponApplicableForFreeShipping) {
// Apply Coupon
$checkout['coupon'] = [
'code' => $coupon->getCode(),
'type' => $coupon->getDiscountType(),
'discount' => (float)$isCouponValidForBasket,
'freeShipping' => $isCouponApplicableForFreeShipping,
];
//mac + mouse coupon
if ($checkout['coupon']['code'] == Coupon::MAC_MOUSE_COUPON_CODE) {
$basketMacItems = $basket->getBasketItems()->filter(function (BasketItem $item) {
if ($item->getProduct()->getVendor()->getId() == Vendor::VENDOR_ID_APPLE && $item->getProduct()->getType()->getId() == ProductType::PRODUCT_TYPE_ID_NOTEBOOK) {
return true;
}
});
$mouseAttribute = $entityManager->getRepository(AttributeOption::class)->findOneById(AttributeOption::ATTRIBUTE_OPTION_ID_MACBOOK_FREE_MOUSE);
/** @var BasketItem $item */
foreach ($basketMacItems as $item) {
$basketAttributeOption = new BasketItemAttributeOption();
$basketAttributeOption->setBasketItem($item);
$basketAttributeOption->setAttributeOption($mouseAttribute);
$entityManager->persist($basketAttributeOption);
}
}
if ($checkout['coupon']['code'] == Coupon::SUMMER_2026_COUPON_CODE) {
$productRepo = $entityManager->getRepository(Product::class);
$giftProduct = $productRepo->find(Product::SUMMER_2026_COUPON_GIFT_ITEM_ID);
if ($giftProduct && $giftProduct->getAvailable() > 0) {
$basketItem = new BasketItem();
$basketItem->setBasket($basket);
$basketItem->setProduct($giftProduct);
$basketItem->setQuantity(1);
$entityManager->persist($basketItem);
}
}
$basket->setCouponCode($couponCode);
$entityManager->flush();
// Save
$request->getSession()->set('checkout', $checkout);
// Success
$json['success'] = $this->getTranslator()->trans('Your coupon discount has been applied');
} else {
if (($coupon->isOnlyOnceUse() && CartHelper::isCouponAlreadyUsed($entityManager, $basket, $couponCode))
|| ($coupon->isOnlyOnceCustomerUse() && CartHelper::isCouponAlreadyUsedThisUser($entityManager, $basket, $couponCode))) {
$json['error'] = $translator->trans('Coupon has already been used');
}
if (empty($json['error']) && !$coupon->isAvailableForDiscountedProducts()) {
$json['error'] = $translator->trans('Coupon does not apply to discounted products');
}
if (empty($json['error'])) {
$json['error'] = $translator->trans('Coupon only applies to certain products');
}
}
return new JsonResponse($json);
}
/**
* @Route("/cart/coupon_remove", name="cart_coupon_remove", defaults={"_locale":""})
* @Route("/{_locale<%supported_locales%>?}/cart/coupon_remove", name="cart_coupon_remove_locale", defaults={"_locale":""})
* @param Request $request
* @return JsonResponse
*/
public function couponRemoveAction(Request $request)
{
$translator = $this->getTranslator();
$checkout = $request->getSession()->get('checkout');
//mac + mouse coupon
if ($checkout['coupon']['code'] == Coupon::MAC_MOUSE_COUPON_CODE) {
$entityManager = $this->getEntityManager();
$basket = $this->getCart($request->getSession()->get('cartId'));
/** @var BasketItem $item */
foreach ($basket->getBasketItems() as $item) {
if ($item->getProduct()->getVendor()->getId() == Vendor::VENDOR_ID_APPLE && $item->getProduct()->getType()->getId() == ProductType::PRODUCT_TYPE_ID_NOTEBOOK) {
/** @var BasketItemAttributeOption $attributeOption */
foreach ($item->getItemAttributes() as $attribute) {
if ($attribute->getAttributeOption()->getId() == AttributeOption::ATTRIBUTE_OPTION_ID_MACBOOK_FREE_MOUSE) {
$entityManager->remove($attribute);
}
}
}
}
$entityManager->flush();
}
if ($checkout['coupon']['code'] == Coupon::SUMMER_2026_COUPON_CODE) {
$entityManager = $this->getEntityManager();
$basket = $this->getCart($request->getSession()->get('cartId'));
foreach ($basket->getBasketItems() as $item) {
if ($item->getProduct()->getId() == Product::SUMMER_2026_COUPON_GIFT_ITEM_ID) {
$entityManager->remove($item);
$entityManager->flush();
}
}
}
unset($checkout['coupon']);
$request->getSession()->set('checkout', $checkout);
$json['error'] = $translator->trans('Your coupon discount has been deleted');
return new JsonResponse($json);
}
/**
* @Route("/cart/addOption", name="cart_add_option", defaults={"_locale":""})
* @Route("/{_locale<%supported_locales%>?}/cart/addOption", name="cart_add_option_locale", defaults={"_locale":""})
* @param Request $request
* @return JsonResponse
*/
public function addOptionAction(Request $request)
{
$json = [];
// Entity Manager
$entityManager = $this->getEntityManager();
// Product Helper
$productHelper = $this->getProductHelper($request);
// Checkout Data
if ($request->getSession()->has('checkout')) {
$checkout = $request->getSession()->get('checkout');
} else {
$checkout = [];
}
// Customer
$customer = $this->getLoginHelper($request)->getLoggedInCustomer();
// Product ID
$productId = $request->request->get('productId');
// Attribute Option ID
$attributeOptionId = $request->request->get('attributeOptionId');
// Product
$product = $entityManager->getRepository(Product::class)->findOneById($productId);
// Attribute Option
$attributeOption = $entityManager->getRepository(AttributeOption::class)->findOneById($attributeOptionId);
if ($product && $attributeOption) {
// Structured Data
$productData = $productHelper->getStructuredDataForProduct($product, 'cart');
// Multi-Store Helper
$multiStore = $this->getMultiStoreHelper($request);
// Domain
$domain = $multiStore->getDomain();
// Cross-sell Attribute Options
$crossSellAttributeOptions = CartHelper::getCrossSellAttributeOptionsByProductTypeId($productData['productTypeId'], $domain->getId());
// Available
if (isset($crossSellAttributeOptions[$attributeOptionId])) {
// Cart
$cart = $this->getCart($request->getSession()->get('cartId'));
if ($cart) {
// Find Item in Cart by Product Id
$found = false;
foreach ($cart->getBasketItems() as $item) {
if ($product->getId() == $item->getProduct()->getId()) {
$found = $item;
if ($item->getItemAttributes()) {
foreach ($item->getItemAttributes() as $attribute) {
$option = $attribute->getAttributeOption();
if (isset($crossSellAttributeOptions[$option->getId()]) && $attributeOption->getAttribute()->getId() == $option->getAttribute()->getId()) {
$found = false;
$json['added'] = $option->getId();
break;
}
}
}
break;
}
}
// Add Attribute Option to Product
if ($found) {
$basketItemAttributeOption = new BasketItemAttributeOption();
$basketItemAttributeOption->setBasketItem($found);
$basketItemAttributeOption->setAttributeOption($attributeOption);
$entityManager->persist($basketItemAttributeOption);
$entityManager->flush();
// Success
$json['success'] = true;
}
}
}
}
return new JsonResponse($json);
}
/**
* @Route("/cart/widget", name="cart_widget", defaults={"_locale":""})
* @Route("/{_locale<%supported_locales%>?}/cart/widget", name="cart_widget_locale", defaults={"_locale":""})
* @param Request $request
* @return Response
* @throws \Exception
*/
public function widgetAction(Request $request)
{
$module = $this->getModuleHelper($request);
return new Response($module->widgetCart());
}
/**
* @param int $giftId
* @param Basket $cart
* @param Domain $domain
*
* @return bool
*/
private function removeGift(int $productId, Basket $cart, Domain $domain): bool {
if ( $productId > 0 && in_array($domain->getId(), [ Domain::DOMAIN_ID_RT_SK, Domain::DOMAIN_ID_RT_CZ, Domain::DOMAIN_ID_RT_HU, Domain::DOMAIN_ID_RT_EU ]) ) {
if ( $cart && $cart->getBasketItems()->count() > 0 ) {
$giftBasketItem = null;
$removeGift = true;
/** @var BasketItem $basketItem */
foreach ( $cart->getBasketItems() as $basketItem ) {
if ( $basketItem->getProduct()->getId() == $productId ) {
$giftBasketItem = $basketItem;
}
if ( $basketItem->getProduct()?->getType()?->getId() == ProductType::PRODUCT_TYPE_ID_NOTEBOOK ) {
$productDomainMeta = $basketItem->getProduct()->getDomainMeta($domain);
if ( $productDomainMeta !== false && $productDomainMeta->isDiscounted() && $productDomainMeta->isDiscountValid() ) {
$removeGift = false;
}
}
if ( !is_null($giftBasketItem) && $removeGift === false ) {
break;
}
}
if ( !is_null($giftBasketItem) && $removeGift === true ) {
$this->getEntityManager()->remove($giftBasketItem);
$this->getEntityManager()->flush();
return true;
}
}
}
return false;
}
}