database = $database; $this->cartService = $cartService; $this->oc = $registry; $this->settings = $settings; $this->telegramService = $telegramService; $this->logger = $logger; $this->telecartCustomerService = $telegramCustomerService; $this->ocCustomerService = $ocCustomerService; $this->orderMetaService = $orderMetaService; } /** * @throws Throwable * @throws JsonException */ public function create(array $data, array $meta = []): array { $now = Carbon::now(); $storeId = $this->settings->get('store.oc_store_id'); $storeName = $this->settings->config()->getApp()->getAppName(); $orderStatusId = $this->settings->config()->getOrders()->getOrderDefaultStatusId(); $customerGroupId = $this->settings->config()->getOrders()->getOcCustomerGroupId(); $languageId = $this->settings->config()->getApp()->getLanguageId(); $currencyId = $this->oc->currency->getId($this->oc->session->data['currency']); $currencyCode = $this->oc->session->data['currency']; $currencyValue = $this->oc->currency->getValue($this->oc->session->data['currency']); $cart = $this->cartService->getCart(); $total = $cart['total'] ?? 0; $products = $cart['products'] ?? []; $totals = $cart['totals'] ?? []; // Получаем telegram_user_id из tgData $telegramUserId = Arr::get($data['tgData'] ?? [], 'user.id'); $telegramUserdata = Arr::get($data['tgData'] ?? [], 'user'); if (! $telegramUserId) { throw new RuntimeException('Telegram user id is required.'); } $customOrderFields = $this->customOrderFields($data); $orderData = [ 'store_id' => $storeId, 'store_name' => $storeName, 'firstname' => $data['firstname'] ?? '', 'lastname' => $data['lastname'] ?? '', 'email' => $data['email'] ?? '', 'telephone' => $data['telephone'] ?? '', 'comment' => $data['comment'] ?? '', 'payment_method' => $data['payment_method'] ?? '', 'shipping_address_1' => $data['shipping_address_1'] ?? '', 'shipping_city' => $data['shipping_city'] ?? '', 'shipping_zone' => $data['shipping_zone'] ?? '', 'shipping_postcode' => $data['shipping_postcode'] ?? '', 'total' => $total, 'order_status_id' => $orderStatusId, 'ip' => $meta['ip'] ?? '', 'forwarded_ip' => $meta['ip'] ?? '', 'user_agent' => $meta['user_agent'] ?? '', 'date_added' => $now, 'date_modified' => $now, 'language_id' => $languageId, 'currency_id' => $currencyId, 'currency_code' => $currencyCode, 'currency_value' => $currencyValue, 'customer_group_id' => $customerGroupId, ]; try { $this->database->beginTransaction(); $telecartCustomer = $this->telecartCustomerService->saveOrUpdate($telegramUserdata); $telecartCustomerId = (int) $telecartCustomer['id']; $ocCustomer = $this->ocCustomerService->findOrCreateByTelecartCustomerId($telecartCustomerId, $orderData); $ocCustomerId = (int) $ocCustomer['customer_id']; $orderData['customer_id'] = $ocCustomerId; $this->database->insert(db_table('order'), $orderData); $orderId = $this->database->lastInsertId(); // Insert products $this->insertProducts($products, $orderId); // Insert totals $this->insertTotals($totals, $orderId); // Insert history $this->insertHistory($orderId, $orderStatusId, $customOrderFields, $now); // Insert order meta data if ($customOrderFields) { $this->orderMetaService->insert($orderId, $storeId, $customOrderFields, $telecartCustomerId); } $this->telecartCustomerService->increaseOrdersCount($telecartCustomerId); $this->database->commitTransaction(); } catch (Throwable $exception) { $this->database->rollBackTransaction(); throw $exception; } $this->cartService->flush(); $orderData['order_id'] = $orderId; $orderData['total_numeric'] = $orderData['total'] ?? 0; $orderData['total'] = $cart['total_text'] ?? ''; $this->sendNotifications($orderData, $data['tgData']); $dateTimeFormatted = ''; try { $dateTimeFormatted = $now->format('d.m.Y H:i'); } catch (Exception $exception) { $this->logger->error($exception->getMessage(), ['exception' => $exception]); } return [ 'id' => $orderData['order_id'], 'created_at' => $dateTimeFormatted, 'total' => $orderData['total'], 'final_total_numeric' => $orderData['total_numeric'], 'currency' => $currencyCode, 'products' => $products, ]; } private function sendNotifications(array $orderData, array $tgInitData): void { $variables = [ '{store_name}' => $orderData['store_name'], '{order_id}' => $orderData['order_id'], '{customer}' => $orderData['firstname'] . ' ' . $orderData['lastname'], '{email}' => $orderData['email'], '{phone}' => $orderData['telephone'], '{comment}' => $orderData['comment'], '{address}' => $orderData['shipping_address_1'], '{total}' => $orderData['total'], '{ip}' => $orderData['ip'], '{created_at}' => $orderData['date_added'], ]; $chatId = $this->settings->config()->getTelegram()->getChatId(); $template = $this->settings->config()->getTelegram()->getOwnerNotificationTemplate(); if ($chatId && $template) { $message = $this->telegramService->prepareMessage($template, $variables); try { $this->telegramService->sendMessage($chatId, $message); } catch (Throwable $exception) { $this->logger->error( 'Telegram sendMessage to owner error.', [ 'exception' => $exception, 'chat_id' => $chatId, 'message' => $message, ], ); } } $allowsWriteToPm = Arr::get($tgInitData, 'user.allows_write_to_pm', false); $customerChatId = Arr::get($tgInitData, 'user.id'); $template = $this->settings->config()->getTelegram()->getCustomerNotificationTemplate(); if ($allowsWriteToPm && $customerChatId && $template) { $message = $this->telegramService->prepareMessage($template, $variables); try { $this->telegramService->sendMessage($customerChatId, $message); } catch (Throwable $exception) { $this->logger->error( "Telegram sendMessage to customer error.", [ 'exception' => $exception, 'chat_id' => $chatId, 'message' => $message, ], ); } } } private function formatHistoryComment(array $customFields): string { $additionalString = ''; if ($customFields) { $additionalString = "\n\nДополнительная информация по заказу:\n"; foreach ($customFields as $field => $value) { $additionalString .= $field . ': ' . $value . "\n"; } } return "Заказ оформлен через Telegram Mini App.$additionalString"; } private function customOrderFields(array $data): array { return Arr::except($data, [ 'firstname', 'lastname', 'email', 'telephone', 'comment', 'shipping_address_1', 'shipping_city', 'shipping_zone', 'shipping_postcode', 'payment_method', 'tgData', ]); } public function insertTotals(array $totals, int $orderId): void { foreach ($totals as $total) { $this->database->insert(db_table('order_total'), [ 'order_id' => $orderId, 'code' => $total['code'], 'title' => $total['title'], 'value' => $total['value'], 'sort_order' => $total['sort_order'], ]); } } /** * @param int $orderId * @param int $orderStatusId * @param array $customOrderFields * @param Carbon $now * @return void */ public function insertHistory(int $orderId, int $orderStatusId, array $customOrderFields, Carbon $now): void { $history = [ 'order_id' => $orderId, 'order_status_id' => $orderStatusId, 'notify' => 0, 'comment' => $this->formatHistoryComment($customOrderFields), 'date_added' => $now, ]; $this->database->insert(db_table('order_history'), $history); } private function insertProducts($products, int $orderId): void { foreach ($products as $product) { $this->database->insert(db_table('order_product'), [ 'order_id' => $orderId, 'product_id' => $product['product_id'], 'name' => $product['name'], 'model' => $product['model'], 'quantity' => $product['quantity'], 'price' => $product['price_numeric'], 'total' => $product['total_numeric'], 'reward' => $product['reward_numeric'], ]); $orderProductId = $this->database->lastInsertId(); foreach ($product['option'] as $option) { $this->database->insert(db_table('order_option'), [ 'order_id' => $orderId, 'order_product_id' => $orderProductId, 'product_option_id' => $option['product_option_id'], 'product_option_value_id' => $option['product_option_value_id'], 'name' => $option['name'], 'value' => $option['value'], 'type' => $option['type'], ]); } } } }