317 lines
12 KiB
PHP
Executable File
317 lines
12 KiB
PHP
Executable File
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services;
|
|
|
|
use Carbon\Carbon;
|
|
use Exception;
|
|
use JsonException;
|
|
use Openguru\OpenCartFramework\OpenCart\Decorators\OcRegistryDecorator;
|
|
use Openguru\OpenCartFramework\QueryBuilder\Connections\ConnectionInterface;
|
|
use Openguru\OpenCartFramework\Support\Arr;
|
|
use Openguru\OpenCartFramework\Telegram\TelegramService;
|
|
use Psr\Log\LoggerInterface;
|
|
use RuntimeException;
|
|
use Throwable;
|
|
|
|
class OrderCreateService
|
|
{
|
|
private ConnectionInterface $database;
|
|
private CartService $cartService;
|
|
private OcRegistryDecorator $oc;
|
|
private SettingsService $settings;
|
|
private TelegramService $telegramService;
|
|
private LoggerInterface $logger;
|
|
private TelecartCustomerService $telecartCustomerService;
|
|
private OcCustomerService $ocCustomerService;
|
|
private OrderMetaService $orderMetaService;
|
|
|
|
public function __construct(
|
|
ConnectionInterface $database,
|
|
CartService $cartService,
|
|
OcRegistryDecorator $registry,
|
|
SettingsService $settings,
|
|
TelegramService $telegramService,
|
|
LoggerInterface $logger,
|
|
TelecartCustomerService $telegramCustomerService,
|
|
OcCustomerService $ocCustomerService,
|
|
OrderMetaService $orderMetaService
|
|
) {
|
|
$this->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'],
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
}
|