custom/plugins/MagmodulesWebshopnl/src/Api/Controller/OrderProcess.php line 570
<?phpdeclare(strict_types=1);namespace MagmodulesWebshopnl\Api\Controller;use Doctrine\DBAL\Exception\UniqueConstraintViolationException;use MagmodulesWebshopnl\Core\Content\WebShopOrder\WebShopOrderEntity;use MagmodulesWebshopnl\Service\WebShopLogger;use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryStates;use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates;use Shopware\Core\Checkout\Order\OrderStates;use Shopware\Core\Content\Product\ProductEntity;use Shopware\Core\Defaults;use Shopware\Core\Framework\Context;use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\OrFilter;use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;use Shopware\Core\Framework\Util\Random;use Shopware\Core\Framework\Uuid\Uuid;use Shopware\Core\System\Currency\CurrencyEntity;use Shopware\Core\System\NumberRange\NumberRangeEntity;use Shopware\Core\System\SalesChannel\SalesChannelEntity;use Shopware\Core\System\SystemConfig\SystemConfigService;use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;use Symfony\Component\HttpFoundation\JsonResponse;class OrderProcess extends AbstractController{public function __construct(private SystemConfigService $systemConfigService,private WebShopLogger $webShopLogger,private EntityRepository $orderRepository,private EntityRepository $salesChannelRepository,private EntityRepository $languageRepository,private EntityRepository $stateMachineRepository,private EntityRepository $stateMachineStateRepository,private EntityRepository $customerRepository,private EntityRepository $paymentRepository,private EntityRepository $salutationRepository,private EntityRepository $numberRangeRepository,private EntityRepository $shippingMethodRepository,private EntityRepository $numberRangeStateRepository,private EntityRepository $webshopnlOrderRepository,private EntityRepository $productRepository,private EntityRepository $countryRepository,private EntityRepository $currencyRepository,) {}public function processOrder(array $order, string $salesChannelId, Context $context): array{if ($this->getCheckExistOrder($order, $context) > 0) {$logdata = $this->getLoggerData($order, "Rejected", "Order already imported");$log = $this->systemConfigService->get('MagmodulesWebshopnl.settings.debug', $salesChannelId);if ($log) {$this->webShopLogger->addOrderLog($context, $logdata);}return $logdata;}return $this->orderDataCreate($order, $salesChannelId, $context);}private function getCheckExistOrder(array $order, Context $context): int{return $this->webshopnlOrderRepository->searchIds((new Criteria())->addFilter(new EqualsFilter('webShopOrderId', $order['order_id'])),$context)->getTotal();}private function getLoggerData(array $order, string $status, string $message): array{return ['order_id' => $order['order_id'] ?? null,'merchant_id' => $order['merchant_id'] ?? null,'status' => $status,'message' => $message,];}private function orderDataCreate(array $orderData, string $salesChannelId, Context $context): array{$orderData['billing_address'] = $orderData['billing_address'] ?? $orderData['delivery_address'];$orderData['delivery_address'] = $orderData['delivery_address'] ?? $orderData['billing_address'];$billingHash = md5(json_encode($orderData['billing_address']));$shippingHash = md5(json_encode($orderData['delivery_address']));$salesChannelEntity = $this->getSaleChannelDetails($salesChannelId, $context);$orderId = Uuid::randomHex();$billingAddress = $this->getOrderAddressData($orderId,$orderData['billing_address'],$salesChannelEntity->getCountryId(),$context);if ($billingHash !== $shippingHash) {$shippingAddress = $this->getOrderAddressData($orderId,$orderData['delivery_address'],$salesChannelEntity->getCountryId(),$context);} else {$shippingAddress = $billingAddress;}$orderCustomerId = $this->findOrCreateCustomerId($orderData['billing_address']['email'],$salesChannelId,$context,$salesChannelEntity->getLanguageId(),$billingAddress,$shippingAddress);/** @var CurrencyEntity $currency */$currency = $this->getCurrency($orderData['currency'] ?? '', $context)?? $salesChannelEntity->getCurrency();$orderNumberRange = $this->getOrderNumberRange($context);$nextOrderNumber = (string)$orderNumberRange->getStart();if ($orderNumberRange->getState() !== null) {$nextOrderNumber = (string)($orderNumberRange->getState()->getLastValue() + 1);}$order = [];$order['id'] = $orderId;$order['billingAddress'] = $billingAddress;$order['shippingAddress'] = $shippingAddress;$order['currencyId'] = $currency->getId();$order['orderNumber'] = $nextOrderNumber;$order['orderCustomer'] = $this->getOrderCustomerData($orderId,$orderCustomerId,$orderData['billing_address']['email'],$billingAddress,$context);$order['languageId'] = $salesChannelEntity->getLanguageId();$order['salesChannelId'] = $salesChannelId;$order['price'] = $this->getPrice($orderData);$order['lineItems'] = $this->getLineItems($orderId, $orderData, $context);$order['orderDateTime'] = (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT);$order['customerId'] = $orderCustomerId;$order['currencyFactor'] = $currency->getFactor();$order['deepLinkCode'] = Random::getBase64UrlString(32);$order['transactions'] = $this->getOrderTransactions($orderId, $orderData, $context);$order['deliveries'] = $this->getOrderDeliveries($orderId, $shippingAddress['id'], $orderData, $context);$order['shippingCosts'] = $this->getShippingCost($orderData);$order['stateId'] = $this->getInitialStateIdByName(OrderStates::STATE_MACHINE, $context);$order['orderDeliveryStateId'] = $this->getInitialStateIdByName(OrderDeliveryStates::STATE_MACHINE, $context);$order['itemRounding'] = $currency->getItemRounding()->jsonSerialize();$order['totalRounding'] = $currency->getTotalRounding()->jsonSerialize();$log = $this->systemConfigService->get('MagmodulesWebshopnl.settings.debug', $salesChannelId);try {$this->orderRepository->create([$order], $context);$this->updateOrderNumber($orderNumberRange, (int)$nextOrderNumber, $context);$this->addWebShopOrder($order['id'], $orderData, $context, $salesChannelId);if ($log) {$status = "Confirmed";$message = "Order was imported";$this->webShopLogger->addOrderLog($context, $this->getLoggerData($orderData, $status, $message));}} catch (UniqueConstraintViolationException $exception) {if ($log) {$status = "Rejected";$message = $exception->getMessage();$this->webShopLogger->addOrderLog($context, $this->getLoggerData($orderData, $status, $message));}}return $order;}private function addWebShopOrder(string $orderId, array $getOrder, Context $context, string $salesChannelId): void{$this->webshopnlOrderRepository->create([['id' => Uuid::randomHex(),'salesChannelId' => $salesChannelId,'webShopOrderId' => $getOrder['order_id'],'status' => 'imported','orderId' => $orderId,'merchantId' => $getOrder['merchant_id'],],], $context);}private function getOrderDeliveries(string $orderId,string $shippingAddressId,array $orderData,Context $context): array {$shippingDateEarliest = date("Y/m/d");$latestDate = strtotime("+4 day", strtotime($shippingDateEarliest));$shippingDateLatest = date('Y/m/d', $latestDate);return [['orderId' => $orderId,//'shippingOrderAddressId' => $shippingAddressId,'shippingMethodId' => $this->getShippingMethodId($context),'stateId' => $this->getInitialStateIdByName(OrderDeliveryStates::STATE_MACHINE, $context),'trackingCodes' => [],'shippingDateEarliest' => $shippingDateEarliest,'shippingDateLatest' => $shippingDateLatest,'shippingCosts' => $this->getShippingCost($orderData),],];}private function getShippingMethodId($context){$paymentCriteria = new Criteria();$paymentCriteria->addFilter(new EqualsFilter('name', 'webshopnl'));return $this->shippingMethodRepository->search($paymentCriteria, $context)->first()->getId();}private function getOrderTransactions(string $orderId, array $orderData, Context $context): array{if (array_key_exists('paid_at', $orderData) && $orderData['paid_at'] !== null) {$stateId = $this->getIdByTransactionStateName(OrderTransactionStates::STATE_PAID,$context);} else {$stateId = $this->getInitialStateIdByName(OrderTransactionStates::STATE_MACHINE,$context);}return [['orderId' => $orderId,'paymentMethodId' => $this->getPaymentMethodID($context),'amount' => $this->getTransactionAmount($orderData),'stateId' => $stateId,],];}private function getPaymentMethodID(Context $context): ?string{$paymentCriteria = new Criteria();$paymentCriteria->addFilter(new EqualsFilter('name', 'webshopnl'));return $this->paymentRepository->searchIds($paymentCriteria, $context)->firstId();}private function getTransactionAmount(array $orderData): array{$quantity = $orderData['items']['quantity'];$productIds = $orderData['items']['products'];foreach ($productIds as $data) {$price = $data['per_item'];}return ["quantity" => $quantity,"taxRules" => [["taxRate" => 0,"percentage" => 0,],],"listPrice" => null,"unitPrice" => $price,"totalPrice" => $price * $quantity / 100,"referencePrice" => null,"calculatedTaxes" => [["tax" => 0,"price" => 0,"taxRate" => 0,],],"regulationPrice" => null,];}private function getLineItems(string $orderId, array $orderData, Context $context): array{$lineItemReturn = [];foreach ($orderData['items']['products'] as $lineItem) {$lineItemNew = ['id' => Uuid::randomHex(),'orderId' => $orderId,'payload' => [],'label' => $lineItem['name'],'quantity' => $lineItem['quantity'],'price' => $this->getOrderLineItemPrice($lineItem),'removable' => true,'stackable' => true,'type' => 'product','identifier' => $lineItem['remote_id'],];if ($product = $this->getProductEntity($lineItem['remote_id'], $context)) {$lineItemNew['productId'] = $product->getId();$lineItemNew['referencedId'] = $product->getId();$lineItemNew['payload'] = ['stock' => $product->getStock(),'productNumber' => $product->getProductNumber(),];}$lineItemReturn[] = $lineItemNew;}return $lineItemReturn;}private function getProductEntity($productId, $context): ?ProductEntity{$criteria = new Criteria();$criteria->addFilter(new EqualsFilter('id', $productId));return $this->productRepository->search($criteria, $context)->first();}private function getOrderLineItemPrice(array $lineItem): array{return ["quantity" => $lineItem['quantity'],"taxRules" => [["taxRate" => 0,"extensions" => [],"percentage" => 0,],],"listPrice" => null,"unitPrice" => $lineItem['per_item'] / 100,"totalPrice" => ($lineItem['per_item'] / 100) * $lineItem['quantity'],"referencePrice" => null,"calculatedTaxes" => [["tax" => 0,"price" => 0,"taxRate" => 0,"extensions" => [],],],];}private function getOrderCustomerData(string $orderId,$customerId,string $email,array $billingAddress,Context $context): array {return ['customerId' => $customerId,'orderId' => $orderId,'email' => $email,'salutationId' => $this->getValidSalutationId($context),'firstName' => $billingAddress['firstName'],'lastName' => $billingAddress['lastName'],];}private function getShippingCost(array $orderData): array{return ["quantity" => $orderData['items']['quantity'],"taxRules" => [["taxRate" => 0,"extensions" => [],"percentage" => 0,],],"listPrice" => null,"unitPrice" => 0,"totalPrice" => $orderData['items']['delivery_cost'] / 100,"referencePrice" => null,"calculatedTaxes" => [["tax" => 0,"price" => 0,"taxRate" => 0,"extensions" => [],],],"regulationPrice" => null,];}private function getOrderNumberRange(Context $context): NumberRangeEntity{$criteria = new Criteria();$criteria->addFilter(new EqualsFilter('type.technicalName', 'order'));$criteria->addAssociation('state');return $this->numberRangeRepository->search($criteria, $context)->first();}private function getPrice(array $orderData): array{return ["totalPrice" => $orderData['items']['total'] / 100,"netPrice" => $orderData['items']['total'] / 100,"rawTotal" => $orderData['items']['total'] / 100,"taxRules" => [["taxRate" => 0,"extensions" => [],"percentage" => 0,],],"taxStatus" => "gross","positionPrice" => $orderData['items']['products_cost'],"calculatedTaxes" => [["tax" => 0,"price" => 0,"taxRate" => 0,"extensions" => [],],],];}private function updateOrderNumber(NumberRangeEntity $orderNumberRange, int $newValue, Context $context): void{$numberRange = ['id' => $orderNumberRange->getState()?->getId() ?? Uuid::randomHex(),'numberRangeId' => $orderNumberRange->getId(),'lastValue' => $newValue,];$this->numberRangeStateRepository->upsert([$numberRange], $context);}private function findOrCreateCustomerId(string $email,string $salesChannelId,Context $context,string $languageId,array $billingAddress,array $shippingAddress): string {$criteria = new Criteria();$criteria->addFilter(new EqualsFilter('email', $email));$customerId = $this->customerRepository->searchIds($criteria, $context)->firstId();if ($customerId) {return $customerId;}$customerId = Uuid::randomHex();$this->customerRepository->create([['id' => $customerId,'groupId' => $this->systemConfigService->get('MagmodulesWebshopnl.settings.defaultCustomerGroup',$salesChannelId),'defaultPaymentMethodId' => $this->getValidPaymentMethodId($salesChannelId, $context),'salesChannelId' => $salesChannelId,'languageId' => $languageId,'defaultBillingAddress' => $billingAddress,'defaultShippingAddress' => $shippingAddress,'customerNumber' => "10142",'firstName' => $billingAddress['firstName'],'lastName' => $billingAddress['lastName'],'email' => $email,],], $context);return $customerId;}private function getValidPaymentMethodId(?string $salesChannelId, Context $context): string{$criteria = (new Criteria())->setLimit(1)->addFilter(new EqualsFilter('active', true));if ($salesChannelId) {$criteria->addFilter(new EqualsFilter('salesChannels.id', $salesChannelId));}/** @var string $id */$id = $this->paymentRepository->searchIds($criteria, $context)->firstId();return $id;}private function getIdByTransactionStateName(string $name, Context $context): ?string{$stateMachineCriteria = new Criteria();$stateMachineCriteria->addFilter(new EqualsFilter('technicalName', $name));return $this->stateMachineStateRepository->search($stateMachineCriteria, $context)->first()?->getId();}private function getInitialStateIdByName(string $name, $context){$stateMachineCriteria = new Criteria();$stateMachineCriteria->addFilter(new EqualsFilter('technicalName', $name));return $this->stateMachineRepository->search($stateMachineCriteria, $context)->first()->getInitialStateId();}private function getSaleChannelDetails(string $salesChannelId, Context $context): SalesChannelEntity{$criteria = new Criteria();$criteria->addAssociation('currency');$criteria->addFilter(new EqualsFilter('id', $salesChannelId));return $this->salesChannelRepository->search($criteria, $context)->first();}private function getLanguageDetails(Context $context){$criteria = new Criteria();$criteria->addFilter(new EqualsFilter('locale.code', 'en-GB'));return $this->languageRepository->search($criteria, $context)->first()->getId();}private function getOrderAddressData(string $orderId,array $addressData,string $fallbackCountryId,Context $context): array {return ['id' => Uuid::randomHex(),'countryId' => $this->getCountryIdByCode($addressData['country_code'], $context) ?? $fallbackCountryId,'orderId' => $orderId,'salutationId' => $this->getValidSalutationId($context),'firstName' => $addressData['first_name'],'lastName' => $addressData['surname'],'street' => $addressData['street_name'],'zipcode' => $addressData['zip_code'],'city' => $addressData['city'],'additionalAddressLine1' => $addressData['extra_address_information'],'created_at' => (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT),];}private function getValidSalutationId(Context $context): string{$criteria = (new Criteria())->setLimit(1)->addSorting(new FieldSorting('salutationKey'));/** @var string $id */$id = $this->salutationRepository->searchIds($criteria, $context)->firstId();return $id;}public function getOrderStatus(string $orderId, Context $context){$getOrderCriteria = new Criteria();$getOrderCriteria->addFilter(new OrFilter([new EqualsFilter('orderId', $orderId),new EqualsFilter('webShopOrderId', $orderId)]));$getOrderCriteria->addAssociation('order.stateMachineState');$order = $this->webshopnlOrderRepository->search($getOrderCriteria, $context)->first();if ($order instanceof WebShopOrderEntity && $order->getOrder() !== null) {return new JsonResponse(['id' => $orderId,'order_status' => $order->getOrder()->getStateMachineState()?->getTechnicalName() ?? 'error',]);}return new JsonResponse(['status' => "No order found",]);}private function getCountryIdByCode(string $code, Context $context): ?string{$criteria = new Criteria();$criteria->addFilter(new EqualsFilter('iso', $code));return $this->countryRepository->searchIds($criteria, $context)->firstId();}private function getCurrency(string $code, Context $context): ?CurrencyEntity{if (empty($code)) {return null;}$criteria = new Criteria();$criteria->addFilter(new EqualsFilter('isoCode', $code));return $this->currencyRepository->search($criteria, $context)->first();}}