diff --git a/src/Controller/OrderController.php b/src/Controller/OrderController.php index ab3ecd2..4da56e9 100644 --- a/src/Controller/OrderController.php +++ b/src/Controller/OrderController.php @@ -5,15 +5,20 @@ namespace Shopsys\ConvertimBundle\Controller; use Convertim\Order\ConvertimOrderDataFactory; +use Convertim\Order\ConvertimSaveOrderResponse; use Shopsys\ConvertimBundle\Model\Convertim\ConvertimConfigProvider; use Shopsys\ConvertimBundle\Model\Convertim\ConvertimLogger; use Shopsys\ConvertimBundle\Model\Convertim\Exception\ConvertimException; use Shopsys\ConvertimBundle\Model\Order\OrderDetailFactory; +use Shopsys\ConvertimBundle\Model\Order\OrderFacade; use Shopsys\ConvertimBundle\Model\Order\OrderValidator; +use Shopsys\FrameworkBundle\Component\Router\DomainRouterFactory; +use Shopsys\FrameworkBundle\Model\Order\OrderUrlGenerator; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Throwable; class OrderController extends AbstractConvertimController @@ -22,12 +27,18 @@ class OrderController extends AbstractConvertimController * @param \Shopsys\ConvertimBundle\Model\Order\OrderDetailFactory $orderDetailFactory * @param \Shopsys\ConvertimBundle\Model\Convertim\ConvertimLogger $convertimLogger * @param \Shopsys\ConvertimBundle\Model\Order\OrderValidator $orderValidator + * @param \Shopsys\ConvertimBundle\Model\Order\OrderFacade $orderFacade + * @param \Shopsys\FrameworkBundle\Component\Router\DomainRouterFactory $domainRouterFactory + * @param \Shopsys\FrameworkBundle\Model\Order\OrderUrlGenerator $orderUrlGenerator * @param \Shopsys\ConvertimBundle\Model\Convertim\ConvertimConfigProvider $convertimConfigProvider */ public function __construct( protected readonly OrderDetailFactory $orderDetailFactory, protected readonly ConvertimLogger $convertimLogger, protected readonly OrderValidator $orderValidator, + protected readonly OrderFacade $orderFacade, + protected readonly DomainRouterFactory $domainRouterFactory, + protected readonly OrderUrlGenerator $orderUrlGenerator, ConvertimConfigProvider $convertimConfigProvider, ) { parent::__construct($convertimConfigProvider); @@ -75,4 +86,69 @@ public function checkOrder(Request $request): Response return $this->convertimLogger->logGenericException($e); } } + + /** + * @param \Symfony\Component\HttpFoundation\Request $request + * @return \Symfony\Component\HttpFoundation\Response + */ + #[Route('/save-order')] + public function saveOrder(Request $request): Response + { + if ($this->isProtectedRequest($request) === false) { + return $this->invalidAuthorizationResponse(); + } + + try { + $rawData = json_decode($request->getContent(), true, 512, JSON_THROW_ON_ERROR); + $convertimOrderDataFactory = new ConvertimOrderDataFactory(); + $convertimOrderData = $convertimOrderDataFactory->createConvertimOrderDataFromJsonArray($rawData); + + $order = $this->orderFacade->saveOrder($convertimOrderData); + + $router = $this->domainRouterFactory->getRouter($order->getDomainId()); + + $saveOrderResponse = new ConvertimSaveOrderResponse( + $order->getUuid(), + $order->getNumber(), + $this->orderUrlGenerator->getOrderDetailUrl($order), + $router->generate( + 'front_order_paid', + [ + 'orderIdentifier' => $order->getUuid(), + 'orderEmail' => $order->getEmail(), + 'orderPaymentType' => $order->getPayment()->getType(), + 'orderUrlHash' => $order->getUrlHash(), + 'orderPaymentStatusPageValidityHash' => $order->getOrderPaymentStatusPageValidityHash(), + ], + UrlGeneratorInterface::ABSOLUTE_URL, + ), + $router->generate( + 'front_order_paid', + [ + 'orderIdentifier' => $order->getUuid(), + 'orderEmail' => $order->getEmail(), + 'orderPaymentType' => $order->getPayment()->getType(), + 'orderUrlHash' => $order->getUrlHash(), + 'orderPaymentStatusPageValidityHash' => $order->getOrderPaymentStatusPageValidityHash(), + ], + UrlGeneratorInterface::ABSOLUTE_URL, + ), + $router->generate( + 'front_order_sent', + [ + 'orderUuid' => $order->getUuid(), + 'orderPaymentType' => $order->getPayment()->getType(), + ], + UrlGeneratorInterface::ABSOLUTE_URL, + ), + [], + ); + + return new JsonResponse($saveOrderResponse); + } catch (ConvertimException $e) { + return $this->convertimLogger->logConvertimException($e); + } catch (Throwable $e) { + return $this->convertimLogger->logGenericException($e); + } + } } diff --git a/src/Model/Order/ConvertimOrderDataToCartMapper.php b/src/Model/Order/ConvertimOrderDataToCartMapper.php index 809905f..b374d81 100644 --- a/src/Model/Order/ConvertimOrderDataToCartMapper.php +++ b/src/Model/Order/ConvertimOrderDataToCartMapper.php @@ -99,7 +99,7 @@ protected function applyConvertimPaymentToCart(ConvertimOrderData $convertimOrde protected function applyConvertimTransportToCart(ConvertimOrderData $convertimOrderData, Cart $cart): void { $transport = $this->transportFacade->getByUuid($convertimOrderData->getTransportData()->getUuid()); - $cartTransportData = $this->cartTransportDataFactory->create($cart, $transport->getUuid(), null); + $cartTransportData = $this->cartTransportDataFactory->create($cart, $transport->getUuid(), $convertimOrderData->getTransportData()->getExtra()?->getPickUpPointCode()); $cartTransportData->watchedPrice = Money::create($convertimOrderData->getTransportData()->getPriceWithVat()); $cart->editCartTransport($cartTransportData); diff --git a/src/Model/Order/ConvertimOrderDataToOrderDataMapper.php b/src/Model/Order/ConvertimOrderDataToOrderDataMapper.php new file mode 100644 index 0000000..c6e4ec3 --- /dev/null +++ b/src/Model/Order/ConvertimOrderDataToOrderDataMapper.php @@ -0,0 +1,258 @@ +getCustomerData(); + + $orderData = $this->orderDataFactory->create(); + $orderData->domainId = $this->domain->getId(); + $orderData->currency = $this->currencyFacade->getDomainDefaultCurrencyByDomainId($this->domain->getId()); + $orderData->firstName = $convertimCustomerData->getFirstName(); + $orderData->lastName = $convertimCustomerData->getLastName(); + $orderData->email = $convertimCustomerData->getEmail(); + $orderData->telephone = $convertimCustomerData->getTelephoneNumberWithPrefix(); + + $convertimBillingAddressData = $convertimCustomerData->getConvertimCustomerBillingAddressData(); + $convertimDeliveryAddressData = $convertimCustomerData->getConvertimCustomerDeliveryAddressData(); + + if ($convertimBillingAddressData !== null) { + $orderData->companyName = $convertimBillingAddressData->getCompanyName(); + $orderData->companyNumber = $convertimBillingAddressData->getIdentificationNumber(); + $orderData->companyTaxNumber = $convertimBillingAddressData->getVatNumber(); + $orderData->isCompanyCustomer = $convertimBillingAddressData->getCompanyName() !== null && $convertimBillingAddressData->getIdentificationNumber() !== null; + $orderData->street = $convertimBillingAddressData->getStreet(); + $orderData->city = $convertimBillingAddressData->getCity(); + $orderData->postcode = $convertimBillingAddressData->getPostcode(); + $orderData->country = $this->getCountryByCode($convertimBillingAddressData->getCountry()); + } else { + $orderData->companyName = $convertimDeliveryAddressData->getCompanyName(); + $orderData->street = $convertimDeliveryAddressData->getStreet(); + $orderData->city = $convertimDeliveryAddressData->getCity(); + $orderData->postcode = $convertimDeliveryAddressData->getPostcode(); + $orderData->country = $this->getCountryByCode($convertimDeliveryAddressData->getCountry()); + } + + $orderData->deliveryAddressSameAsBillingAddress = $convertimOrderData->isBillingAddressSameAsDeliveryAddress(); + + if (!$convertimOrderData->isBillingAddressSameAsDeliveryAddress()) { + $orderData->deliveryFirstName = $convertimDeliveryAddressData->getName(); + $orderData->deliveryLastName = $convertimDeliveryAddressData->getLastName(); + $orderData->deliveryCompanyName = $convertimDeliveryAddressData->getCompanyName(); + $orderData->deliveryTelephone = $convertimDeliveryAddressData->getCurrierTelephoneNumberWithPrefix(); + $orderData->deliveryStreet = $convertimDeliveryAddressData->getStreet(); + $orderData->deliveryCity = $convertimDeliveryAddressData->getCity(); + $orderData->deliveryPostcode = $convertimDeliveryAddressData->getPostCode(); + $orderData->deliveryCountry = $this->getCountryByCode($convertimDeliveryAddressData->getCountry()); + } + + $orderData->note = $convertimOrderData->getNote(); + $orderData->heurekaAgreement = !$convertimOrderData->isDisallowHeurekaVerifiedByCustomers(); + $orderData->origin = 'Convertim'; + + $this->mapProducts($convertimOrderData, $orderData); + $this->mapConvertimTransportDataToOrderItem($convertimOrderData->getTransportData(), $orderData); + $this->mapConvertimPaymentDataToOrderItem($convertimOrderData->getPaymentData(), $orderData); + $this->mapPromoCodes($convertimOrderData, $orderData); + + if ($convertimCustomerData->getCustomerEshopUuid() !== null) { + $orderData->customerUser = $this->customerUserFacade->getByUuid($convertimCustomerData->getCustomerEshopUuid()); + } + + return $orderData; + } + + /** + * @param string|null $countryCode + * @return \Shopsys\FrameworkBundle\Model\Country\Country + */ + protected function getCountryByCode(?string $countryCode): Country + { + $countryReturn = null; + $i = 1; + + foreach ($this->countryFacade->getAllEnabledOnCurrentDomain() as $country) { + if ($i === 1) { + $countryReturn = $country; + } + + if ($country->getCode() === $countryCode) { + return $country; + } + + $i++; + } + + if ($countryReturn === null) { + throw new CountryNotFoundException('No country has been found on current domain.'); + } + + return $countryReturn; + } + + /** + * @param \Convertim\Order\ConvertimOrderPaymentData $convertimOrderPaymentData + * @param \Shopsys\FrameworkBundle\Model\Order\OrderData $orderData + */ + protected function mapConvertimPaymentDataToOrderItem( + ConvertimOrderPaymentData $convertimOrderPaymentData, + OrderData $orderData, + ): void { + $payment = $this->paymentFacade->getByUuid($convertimOrderPaymentData->getUuid()); + $paymentOrderItemData = $this->orderItemDataFactory->create(OrderItemTypeEnum::TYPE_PAYMENT); + $paymentOrderItemData->payment = $payment; + $paymentOrderItemData->name = $payment->getName(); + $paymentOrderItemData->quantity = 1; + $paymentOrderItemData->totalPriceWithVat = Money::create($convertimOrderPaymentData->getPriceWithVat()); + $paymentOrderItemData->totalPriceWithoutVat = Money::create($convertimOrderPaymentData->getPriceWithoutVat()); + $paymentOrderItemData->unitPriceWithVat = Money::create($convertimOrderPaymentData->getPriceWithVat()); + $paymentOrderItemData->unitPriceWithoutVat = Money::create($convertimOrderPaymentData->getPriceWithoutVat()); + $paymentOrderItemData->vatPercent = $payment->getVatForDomain($this->domain->getId())->getPercent(); + $paymentOrderItemData->usePriceCalculation = false; + + $orderData->addItem($paymentOrderItemData); + $orderData->orderPayment = $paymentOrderItemData; + $orderData->payment = $payment; + $orderData->addTotalPrice(new Price($paymentOrderItemData->totalPriceWithoutVat, $paymentOrderItemData->totalPriceWithVat), OrderItemTypeEnum::TYPE_PAYMENT); + } + + /** + * @param \Convertim\Order\ConvertimOrderTransportData $convertimOrderTransportData + * @param \Shopsys\FrameworkBundle\Model\Order\OrderData $orderData + */ + protected function mapConvertimTransportDataToOrderItem( + ConvertimOrderTransportData $convertimOrderTransportData, + OrderData $orderData, + ): void { + $transport = $this->transportFacade->getByUuid($convertimOrderTransportData->getUuid()); + + $transportOrderItemData = $this->orderItemDataFactory->create(OrderItemTypeEnum::TYPE_TRANSPORT); + $transportOrderItemData->transport = $transport; + $transportOrderItemData->name = $transport->getName(); + + $pickupPlaceIdentifier = $convertimOrderTransportData->getExtra()?->getPickUpPointCode(); + + if ($transport->isPersonalPickup()) { + try { + $store = $this->storeFacade->getByUuidAndDomainId( + $pickupPlaceIdentifier, + $this->domain->getId(), + ); + + $transportOrderItemData->name .= ' ' . $store->getName(); + } catch (StoreByUuidNotFoundException) { + } + } + + $transportOrderItemData->quantity = 1; + $transportOrderItemData->totalPriceWithVat = Money::create($convertimOrderTransportData->getPriceWithVat()); + $transportOrderItemData->totalPriceWithoutVat = Money::create($convertimOrderTransportData->getPriceWithoutVat()); + $transportOrderItemData->unitPriceWithVat = Money::create($convertimOrderTransportData->getPriceWithVat()); + $transportOrderItemData->unitPriceWithoutVat = Money::create($convertimOrderTransportData->getPriceWithoutVat()); + $transportOrderItemData->vatPercent = $transport->getVatForDomain($this->domain->getId())->getPercent(); + $transportOrderItemData->usePriceCalculation = false; + + $orderData->addItem($transportOrderItemData); + $orderData->orderTransport = $transportOrderItemData; + $orderData->transport = $transport; + $orderData->pickupPlaceIdentifier = $pickupPlaceIdentifier; + $orderData->addTotalPrice(new Price($transportOrderItemData->totalPriceWithoutVat, $transportOrderItemData->totalPriceWithVat), OrderItemTypeEnum::TYPE_TRANSPORT); + } + + /** + * @param \Convertim\Order\ConvertimOrderData $convertimOrderData + * @param \Shopsys\FrameworkBundle\Model\Order\OrderData $orderData + */ + protected function mapProducts(ConvertimOrderData $convertimOrderData, OrderData $orderData): void + { + foreach ($convertimOrderData->getOrderItemsData() as $convertimOrderItemData) { + $product = $this->productFacade->getByUuid($convertimOrderItemData->getProductId()); + + $orderItemData = $this->orderItemDataFactory->create(OrderItemTypeEnum::TYPE_PRODUCT); + $orderItemData->product = $product; + $orderItemData->catnum = $product->getCatnum(); + $orderItemData->name = $product->getName(); + $orderItemData->unitName = $product->getUnit()->getName(); + $orderItemData->totalPriceWithVat = (Money::create($convertimOrderItemData->getPriceWithVat())->multiply($convertimOrderItemData->getQuantity())); + $orderItemData->totalPriceWithoutVat = (Money::create($convertimOrderItemData->getPriceWithoutVat())->multiply($convertimOrderItemData->getQuantity())); + $orderItemData->quantity = $convertimOrderItemData->getQuantity(); + $orderItemData->unitPriceWithVat = Money::create($convertimOrderItemData->getPriceWithVat()); + $orderItemData->unitPriceWithoutVat = Money::create($convertimOrderItemData->getPriceWithoutVat()); + $orderItemData->vatPercent = $product->getVatForDomain($this->domain->getId())->getPercent(); + $orderItemData->usePriceCalculation = false; + + $orderData->addItem($orderItemData); + $orderData->addTotalPrice(new Price($orderItemData->totalPriceWithoutVat, $orderItemData->totalPriceWithVat), OrderItemTypeEnum::TYPE_PRODUCT); + } + } + + /** + * @param \Convertim\Order\ConvertimOrderData $convertimOrderData + * @param \Shopsys\FrameworkBundle\Model\Order\OrderData $orderData + */ + protected function mapPromoCodes(ConvertimOrderData $convertimOrderData, OrderData $orderData): void + { + $orderData->promoCode = $convertimOrderData->getPromoCodes()[0]->getCode(); + } +} diff --git a/src/Model/Order/OrderFacade.php b/src/Model/Order/OrderFacade.php new file mode 100644 index 0000000..36419ad --- /dev/null +++ b/src/Model/Order/OrderFacade.php @@ -0,0 +1,37 @@ +convertimOrderDataToOrderMapper->mapConvertimOrderDataToOrderData($convertimOrderData); + $deliveryAddressUuid = $convertimOrderData->getCustomerData()->getConvertimCustomerDeliveryAddressData()->getUuid(); + + return $this->placeOrderFacade->placeOrder($orderData, $deliveryAddressUuid); + } +}