src/Controller/Website/Site/CartController.php line 87

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Website\Site;
  3. use App\Controller\Website\ThemeRenderController;
  4. use App\Entity\Generic\Customer\Address;
  5. use App\Entity\Website\Order\Coupon;
  6. use App\Entity\Website\Order\Order;
  7. use App\Entity\Website\Order\OrderItem;
  8. use App\Entity\Website\Order\OrderStatus;
  9. use App\Form\Website\Panel\Order\Coupon\CouponType;
  10. use App\Form\Website\Site\ApplyCouponType;
  11. use App\Form\Website\Site\CheckoutType;
  12. use App\Form\Website\Site\PaymentType;
  13. use App\Service\Payment\PaymentGatewayManager;
  14. use App\Service\Payment\ZarinpalGateway;
  15. use App\Service\Website\Order\OrderCalculatorService;
  16. use App\Service\Website\Setting\SettingService;
  17. use App\Service\WebsiteManager;
  18. use Doctrine\ORM\EntityManagerInterface;
  19. use Symfony\Component\HttpFoundation\Request;
  20. use Symfony\Component\HttpFoundation\Response;
  21. use Symfony\Component\Routing\Annotation\Route;
  22. class CartController extends ThemeRenderController
  23. {
  24.     private SettingService $settingService;
  25.     public function __construct(WebsiteManager $shopManagerEntityManagerInterface $entityManagerSettingService $settingService)
  26.     {
  27.         parent::__construct($shopManager$entityManager);
  28.         $this->settingService $settingService;
  29.     }
  30.     #[Route('/cart'name'app_shop_site_cart')]
  31.     public function showCart(Request $requestEntityManagerInterface $emOrderCalculatorService $orderCalculatorService): Response
  32.     {
  33.         $customer $this->getUser();
  34.         $cartStatus $em->getRepository(OrderStatus::class)->findOneBy(['code' => 'cart']);
  35.         $order $em->getRepository(Order::class)->findOneBy([
  36.             'customer' => $customer,
  37.             'active' => 1,
  38.             'deletedAt' => null,
  39.             'status' => $cartStatus,
  40.         ]);
  41.         if ($order) {
  42. //            $subtotal = array_reduce($order->getOrderItems()->toArray(), fn($carry, $item) => $carry + $item->getPrice() * $item->getQuantity(), 0);
  43.             foreach ($order->getOrderItems() as $orderItem) {
  44.                 $orderedTotal $orderItem->getQuantity();
  45.                 $product $orderItem->getProduct();
  46.                 if ($product->isVariablePriced()) {
  47.                     $productPrice $orderItem->getProductPrice(); // فرض: هر OrderItem به ProductPrice وصله
  48.                     if ($productPrice && $productPrice->getInStock() !== null) {
  49.                         if ($orderedTotal $productPrice->getInStock()) {
  50.                             $orderItem->setQuantity($productPrice->getInStock());
  51.                         }
  52.                     }
  53.                 } else {
  54.                     if ($product->getStock() !== null && $orderedTotal $product->getStock()) {
  55.                         $orderItem->setQuantity($product->getStock());
  56.                     }
  57.                 }
  58.             }
  59.             $em->flush();
  60.             foreach ($order->getOrderItems() as $orderItem) {
  61.                 if ($orderItem->getQuantity() == 0) {
  62.                     $order->removeOrderItem($orderItem);
  63.                 }
  64.             }
  65.             $em->flush();
  66.             $orderCalculatorService->calculate($order);
  67.             $subtotal $order->getTotalPrice();
  68.         } else {
  69.             $subtotal 0;
  70.         }
  71.         return $this->renderUserTemplate('cart.html.twig', [
  72.             'order' => $order,
  73.             'total' => $subtotal ?: null,
  74.         ]);
  75.     }
  76.     #[Route('/cart/checkout'name'cart_checkout')]
  77.     public function checkout(Request $requestEntityManagerInterface $emOrderCalculatorService $orderCalculatorService): Response
  78.     {
  79.         $customer $this->getUser();
  80.         $cartStatus $em->getRepository(OrderStatus::class)->findOneBy(['code' => 'cart']);
  81.         $order $em->getRepository(Order::class)->findOneBy([
  82.             'customer' => $customer,
  83.             'status' => $cartStatus,
  84.             'active' => 1,
  85.             'deletedAt' => null,
  86.         ]);
  87.         if (!$order || $order->getOrderItems()->isEmpty()) {
  88.             $this->addFlash('warning''سبد خرید شما خالی است.');
  89.             return $this->redirectToRoute('app_shop_site_cart');
  90.         }
  91.         $form $this->createForm(CheckoutType::class, null, [
  92.             'website' => $this->shopManager->getShop(),
  93.             'customer' => $customer,
  94.         ]);
  95.         $orderCalculatorService->calculate($order);
  96.         $subtotal $order->getTotalPrice();
  97.         $form->handleRequest($request);
  98.         if ($form->isSubmitted() && $form->isValid()) {
  99.             if ($form->get('use_new_address')->getData()) {
  100.                 $newData $form->get('new_address')->getData();
  101.                 if (
  102.                     $newData['city'] == null ||
  103.                     $newData['state'] == null ||
  104.                     $newData['address'] == null ||
  105.                     $newData['postalCode'] == null
  106.                 ) {
  107.                     $this->addFlash('error''آدرس به درستی وارد نشده');
  108.                     return $this->redirectToRoute('cart_checkout');
  109.                 }
  110.                 $address = new Address();
  111.                 $address->setCity($newData['city']);
  112.                 $address->setState($newData['state']);
  113.                 $address->setCustomer($customer);
  114.                 $address->setAddress($newData['address']);
  115.                 $address->setPostalCode($newData['postalCode']);
  116.             } else {
  117.                 $address $form->get('existing_address')->getData();
  118.             }
  119.             if ($address === null) {
  120.                 $this->addFlash('error''آدرس به درستی وارد نشده است');
  121.                 return $this->redirectToRoute('cart_checkout');
  122.             }
  123.             $em->persist($address);
  124.             $order->setAddress($address);
  125.             $shippingMethod $form->get('shipping_method')->getData();
  126.             $order->setShippingMethod($shippingMethod);
  127.             $order->setShippingCost($shippingMethod->getCost());
  128.             $orderCalculatorService->calculate($order);
  129.             $em->persist($order);
  130.             $em->flush();
  131.             return $this->redirectToRoute('cart_payment');
  132.         }
  133.         return $this->renderUserTemplate('checkout.html.twig', [
  134.             'order' => $order,
  135.             'total' => $subtotal ?: null,
  136.             'form' => $form->createView(),
  137.         ]);
  138.     }
  139.     #[Route('/cart/payment'name'cart_payment')]
  140.     public function payment(Request $requestEntityManagerInterface $emOrderCalculatorService $orderCalculatorService): Response
  141.     {
  142.         $customer $this->getUser();
  143.         $cartStatus $em->getRepository(OrderStatus::class)->findOneBy(['code' => 'cart']);
  144.         /**
  145.          * @var Order $order
  146.          */
  147.         $order $em->getRepository(Order::class)->findOneBy([
  148.             'customer' => $customer,
  149.             'status' => $cartStatus,
  150.             'active' => 1,
  151.             'deletedAt' => null,
  152.         ]);
  153.         if (!$order || $order->getOrderItems()->isEmpty()) {
  154.             $this->addFlash('warning''سبد خرید شما خالی است.');
  155.             return $this->redirectToRoute('app_shop_site_cart');
  156.         }
  157. //        TODO : more than one result
  158. //        $orderCalculatorService->validateStockAndCleanCart($order, $em);
  159.         $orderCalculatorService->calculate($order);
  160.         $couponForm $this->createForm(ApplyCouponType::class, null, ['coupon' => $order->getCoupon()]);
  161.         $couponForm->handleRequest($request);
  162.         if ($couponForm->isSubmitted() && $couponForm->isValid()) {
  163.             $code $couponForm->get('code')->getData();
  164.             /** @var Coupon|null $coupon */
  165.             $coupon $em->getRepository(Coupon::class)->findOneBy([
  166.                 'code' => $code,
  167.                 'website' => $order->getWebsite(),
  168.                 'active' => 1,
  169.                 'deletedAt' => null,
  170.             ]);
  171.             if (!$coupon) {
  172.                 $this->addFlash('danger''کد تخفیف نامعتبر است.');
  173.             } elseif ($coupon->getStartDate() && $coupon->getStartDate() > new \DateTime()) {
  174.                 $this->addFlash('danger''کد تخفیف هنوز فعال نشده است.');
  175.             } elseif ($coupon->getEndDate() && $coupon->getEndDate() < new \DateTime()) {
  176.                 $this->addFlash('danger''کد تخفیف منقضی شده است.');
  177.             } elseif ($coupon->getUsedCount() >= $coupon->getMaxUses()) {
  178.                 $this->addFlash('danger''سقف استفاده از این کد تخفیف پر شده است.');
  179.             } else {
  180.                 $order->setCoupon($coupon);
  181.                 $em->flush();
  182.                 $orderCalculatorService->calculate($order);
  183.             }
  184.             return $this->redirectToRoute('cart_payment');
  185.         }
  186.         $gateWayForm $this->createForm(PaymentType::class, null, [
  187.             'website' => $order->getWebsite(),
  188.             'setting_service' => $this->settingService,
  189.             'user' => $customer,
  190.         ]);
  191.         $gateWayForm->handleRequest($request);
  192.         if ($gateWayForm->isSubmitted() && $gateWayForm->isValid()) {
  193.             $order->setPaymentGateway($gateWayForm->get('gateway')->getData());
  194.             $em->flush();
  195.             return $this->redirectToRoute('cart_start_payment', ['wallet' => $gateWayForm->get('useWallet')->getData()]);
  196.         }
  197.         $subtotal $orderCalculatorService->getSubtotal($order);
  198.         $shippingCost $order->getShippingCost();
  199.         $discount $orderCalculatorService->getDiscount($order);
  200.         $total $orderCalculatorService->getTotalInvoice($order);
  201.         return $this->renderUserTemplate('payment.html.twig', [
  202.             'order' => $order,
  203.             'couponForm' => $couponForm->createView(),
  204.             'subtotal' => $subtotal,              // مجموع قیمت آیتم‌ها
  205.             'shippingCost' => $shippingCost,      // هزینه ارسال
  206.             'discount' => $discount,              // مقدار تخفیف
  207.             'total' => $total,                    // قیمت نهایی پرداختی
  208.             'gateWayForm' => $gateWayForm->createView(),
  209.         ]);
  210.     }
  211.     #[Route('/cart/payment-start'name'cart_start_payment')]
  212.     public function cart_start_payment(EntityManagerInterface $emRequest $requestSettingService $shopSettingServiceZarinpalGateway $zarinpalGateway)
  213.     {
  214.         $useWallet $request->get('wallet'0);
  215.         $customer $this->getUser();
  216.         if ($useWallet) {
  217.             $walletAmount $customer->getWallet();
  218.         } else {
  219.             $walletAmount 0;
  220.         }
  221.         $shop $this->shopManager->getShop();
  222.         $cartStatus $em->getRepository(OrderStatus::class)->findOneBy(['code' => 'cart']);
  223.         $order $em->getRepository(Order::class)->findOneBy([
  224.             'customer' => $customer,
  225.             'status' => $cartStatus,
  226.             'active' => 1,
  227.             'deletedAt' => null,
  228.         ]);
  229.         switch ($order->getPaymentGateway()) {
  230.             case 'zarinpal':
  231.                 $gateway $zarinpalGateway;
  232. //                $gatewayConfig = $shopSettingService->getGatewayConfig($website, 'zarinpal');
  233.                 $response $gateway->pay($order$walletAmount);
  234.                 if ($response->success) {
  235.                     $order->setPaymentGateway('zarinpal');
  236.                     $em->flush();
  237.                     return $this->redirect($response->redirectUrl);
  238.                 }else{
  239.                     $this->addFlash('danger'$response->message ?? 'خطا در شروع پرداخت');
  240.                     return $this->redirectToRoute('cart_checkout');
  241.                 }
  242.                 break;
  243.             default:
  244.                 return $this->redirectToRoute('cart_checkout');
  245.                 break;
  246.         }
  247.     }
  248.     #[Route('/cart/remove/{id}'name'cart_remove_item')]
  249.     public function remove_order_item(OrderItem $orderItemEntityManagerInterface $em)
  250.     {
  251.         $cartStatus $em->getRepository(OrderStatus::class)->findOneBy(['code' => 'cart']);
  252.         $customer $this->getUser();
  253.         $order $em->getRepository(Order::class)->findOneBy([
  254.             'customer' => $customer,
  255.             'status' => $cartStatus,
  256.         ]);
  257.         $order->removeOrderItem($orderItem);
  258.         foreach ($orderItem->getOrderItemAttributes() as $orderItemAttribute) {
  259.             $em->remove($orderItemAttribute);
  260.         }
  261.         if (count($order->getOrderItems()) < 1) {
  262.             $order->setActive(0);
  263.             $order->setDeletedAt(new \DateTime());
  264.         }
  265.         $em->flush();
  266.         return $this->redirectToRoute('app_shop_site_cart');
  267.     }
  268.     #[Route('/cart/remove-coupon'name'cart_remove_coupon')]
  269.     public function cart_remove_coupon(EntityManagerInterface $em)
  270.     {
  271.         $customer $this->getUser();
  272.         $cartStatus $em->getRepository(OrderStatus::class)->findOneBy(['code' => 'cart']);
  273.         $order $em->getRepository(Order::class)->findOneBy([
  274.             'customer' => $customer,
  275.             'status' => $cartStatus,
  276.             'active' => 1,
  277.             'deletedAt' => null,
  278.         ]);
  279.         $order->setCoupon(null);
  280.         $em->flush();
  281.         return $this->redirectToRoute('cart_payment');
  282.     }
  283. }