feat: add FormKit framework support and update dependencies
- Add `telecart_forms` table migration and default checkout form seeder - Implement `FormsHandler` to fetch form schemas - Update `OrderCreateService` to handle custom fields in order comments - Add `update` method to QueryBuilder and Grammar - Add `Arr::except` helper - Update composer dependencies (Carbon, Symfony, PHPUnit, etc.) - Improve `MigratorService` error handling - Add unit tests for new functionality
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Bastion\Handlers;
|
||||
|
||||
use JsonException;
|
||||
use Openguru\OpenCartFramework\Exceptions\EntityNotFoundException;
|
||||
use Openguru\OpenCartFramework\Http\JsonResponse;
|
||||
use Openguru\OpenCartFramework\Http\Request;
|
||||
use Openguru\OpenCartFramework\Http\Response;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
|
||||
class FormsHandler
|
||||
{
|
||||
private Builder $builder;
|
||||
|
||||
public function __construct(Builder $builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws EntityNotFoundException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function getFormByAlias(Request $request): JsonResponse
|
||||
{
|
||||
$alias = 'checkout';
|
||||
//$request->json('alias');
|
||||
if (! $alias) {
|
||||
return new JsonResponse([
|
||||
'error' => 'Form alias is required',
|
||||
], Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
$form = $this->builder->newQuery()
|
||||
->from('telecart_forms')
|
||||
->where('alias', '=', $alias)
|
||||
->firstOrNull();
|
||||
|
||||
if (! $form) {
|
||||
throw new EntityNotFoundException("Form with alias `{$alias}` not found");
|
||||
}
|
||||
|
||||
$schema = json_decode($form['schema'], true, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
return new JsonResponse([
|
||||
'data' => [
|
||||
'alias' => $alias,
|
||||
'friendly_name' => $form['friendly_name'],
|
||||
'is_custom' => filter_var($form['is_custom'], FILTER_VALIDATE_BOOLEAN),
|
||||
'schema' => $schema,
|
||||
'created_at' => $form['created_at'],
|
||||
'updated_at' => $form['updated_at'],
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ use Openguru\OpenCartFramework\Config\Settings;
|
||||
use Openguru\OpenCartFramework\Http\JsonResponse;
|
||||
use Openguru\OpenCartFramework\Http\Request;
|
||||
use Openguru\OpenCartFramework\Http\Response;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Connections\ConnectionInterface;
|
||||
use Openguru\OpenCartFramework\Support\Arr;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
@@ -21,19 +23,25 @@ class SettingsHandler
|
||||
private SettingsService $settingsUpdateService;
|
||||
private CacheInterface $cache;
|
||||
private LoggerInterface $logger;
|
||||
private Builder $builder;
|
||||
private ConnectionInterface $connection;
|
||||
|
||||
public function __construct(
|
||||
BotTokenConfigurator $botTokenConfigurator,
|
||||
Settings $settings,
|
||||
SettingsService $settingsUpdateService,
|
||||
CacheInterface $cache,
|
||||
LoggerInterface $logger
|
||||
LoggerInterface $logger,
|
||||
Builder $builder,
|
||||
ConnectionInterface $connection
|
||||
) {
|
||||
$this->botTokenConfigurator = $botTokenConfigurator;
|
||||
$this->settings = $settings;
|
||||
$this->settingsUpdateService = $settingsUpdateService;
|
||||
$this->cache = $cache;
|
||||
$this->logger = $logger;
|
||||
$this->builder = $builder;
|
||||
$this->connection = $connection;
|
||||
}
|
||||
|
||||
public function configureBotToken(Request $request): JsonResponse
|
||||
@@ -62,17 +70,59 @@ class SettingsHandler
|
||||
'mainpage_blocks',
|
||||
]);
|
||||
|
||||
$data['forms'] = [];
|
||||
|
||||
$forms = $this->builder->newQuery()
|
||||
->from('telecart_forms')
|
||||
->get();
|
||||
|
||||
if ($forms) {
|
||||
foreach ($forms as $form) {
|
||||
$schema = json_decode($form['schema'], true, 512, JSON_THROW_ON_ERROR);
|
||||
$data['forms'][$form['alias']] = [
|
||||
'alias' => $form['alias'],
|
||||
'friendly_name' => $form['friendly_name'],
|
||||
'is_custom' => filter_var($form['is_custom'], FILTER_VALIDATE_BOOLEAN),
|
||||
'schema' => $schema,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return new JsonResponse(compact('data'));
|
||||
}
|
||||
|
||||
public function saveSettingsForm(Request $request): JsonResponse
|
||||
{
|
||||
$this->validate($request->json());
|
||||
$input = $request->json();
|
||||
|
||||
$this->validate($input);
|
||||
|
||||
$this->settingsUpdateService->update(
|
||||
$request->json(),
|
||||
Arr::getWithKeys($input, [
|
||||
'app',
|
||||
'telegram',
|
||||
'metrics',
|
||||
'store',
|
||||
'orders',
|
||||
'texts',
|
||||
'sliders',
|
||||
'mainpage_blocks',
|
||||
]),
|
||||
);
|
||||
|
||||
// Update forms
|
||||
$forms = Arr::get($input, 'forms', []);
|
||||
foreach ($forms as $form) {
|
||||
$schema = json_encode($form['schema'], JSON_THROW_ON_ERROR);
|
||||
$this->builder->newQuery()
|
||||
->where('alias', '=', $form['alias'])
|
||||
->update('telecart_forms', [
|
||||
'friendly_name' => $form['friendly_name'],
|
||||
'is_custom' => $form['is_custom'],
|
||||
'schema' => $schema,
|
||||
]);
|
||||
}
|
||||
|
||||
return new JsonResponse([], Response::HTTP_ACCEPTED);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ class BotTokenConfigurator
|
||||
'webhook_url' => $webhookUrl,
|
||||
];
|
||||
} catch (TelegramClientException $exception) {
|
||||
$this->logger->logException($exception);
|
||||
$this->logger->error($exception->getMessage(), ['exception' => $exception]);
|
||||
if ($exception->getCode() === 404 || $exception->getCode() === 401) {
|
||||
throw new BotTokenConfiguratorException(
|
||||
'Telegram сообщает, что BotToken не верный. Проверьте корректность.'
|
||||
@@ -67,7 +67,7 @@ class BotTokenConfigurator
|
||||
|
||||
throw new BotTokenConfiguratorException($exception->getMessage());
|
||||
} catch (Exception | GuzzleException $exception) {
|
||||
$this->logger->logException($exception);
|
||||
$this->logger->error($exception->getMessage(), ['exception' => $exception]);
|
||||
throw new BotTokenConfiguratorException($exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
2
module/oc_telegram_shop/upload/oc_telegram_shop/bastion/Tasks/CachePruneTask.php
Normal file → Executable file
2
module/oc_telegram_shop/upload/oc_telegram_shop/bastion/Tasks/CachePruneTask.php
Normal file → Executable file
@@ -27,4 +27,4 @@ class CachePruneTask extends BaseMaintenanceTask
|
||||
{
|
||||
return new DateInterval('P1D');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
use Bastion\Handlers\AutocompleteHandler;
|
||||
use Bastion\Handlers\DictionariesHandler;
|
||||
use Bastion\Handlers\FormsHandler;
|
||||
use Bastion\Handlers\LogsHandler;
|
||||
use Bastion\Handlers\SettingsHandler;
|
||||
use Bastion\Handlers\StatsHandler;
|
||||
@@ -24,4 +25,6 @@ return [
|
||||
'getAutocompleteCategoriesFlat' => [AutocompleteHandler::class, 'getCategoriesFlat'],
|
||||
'resetCache' => [SettingsHandler::class, 'resetCache'],
|
||||
'getLogs' => [LogsHandler::class, 'getLogs'],
|
||||
|
||||
'getFormByAlias' => [FormsHandler::class, 'getFormByAlias'],
|
||||
];
|
||||
|
||||
@@ -19,24 +19,25 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4",
|
||||
"ext-pdo": "*",
|
||||
"psr/container": "^2.0",
|
||||
"ext-json": "*",
|
||||
"intervention/image": "^2.7",
|
||||
"vlucas/phpdotenv": "^5.6",
|
||||
"guzzlehttp/guzzle": "^7.9",
|
||||
"symfony/cache": "^5.4",
|
||||
"doctrine/dbal": "^3.10",
|
||||
"ext-json": "*",
|
||||
"ext-pdo": "*",
|
||||
"guzzlehttp/guzzle": "^7.9",
|
||||
"intervention/image": "^2.7",
|
||||
"monolog/monolog": "^2.10",
|
||||
"psr/log": "^1.1"
|
||||
"nesbot/carbon": "^2.73",
|
||||
"php": "^7.4",
|
||||
"psr/container": "^2.0",
|
||||
"psr/log": "^1.1",
|
||||
"symfony/cache": "^5.4",
|
||||
"vlucas/phpdotenv": "^5.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"roave/security-advisories": "dev-latest",
|
||||
"phpstan/phpstan": "^2.1",
|
||||
"phpunit/phpunit": "^9.6",
|
||||
"doctrine/sql-formatter": "^1.3",
|
||||
"mockery/mockery": "^1.6",
|
||||
"phpstan/phpstan": "^2.1",
|
||||
"phpunit/phpunit": "^9.6",
|
||||
"roave/security-advisories": "dev-latest",
|
||||
"squizlabs/php_codesniffer": "*"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
use Openguru\OpenCartFramework\Migrations\Migration;
|
||||
|
||||
return new class extends Migration {
|
||||
public function up(): void
|
||||
{
|
||||
$sql = <<<SQL
|
||||
CREATE TABLE IF NOT EXISTS `telecart_forms` (
|
||||
`id` bigint(11) AUTO_INCREMENT PRIMARY KEY,
|
||||
`alias` varchar(100) NOT NULL,
|
||||
`friendly_name` varchar(100) NOT NULL,
|
||||
`is_custom` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`schema` longtext NOT NULL,
|
||||
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) collate = utf8_unicode_ci
|
||||
SQL;
|
||||
|
||||
$this->database->statement($sql);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Openguru\OpenCartFramework\Migrations\Migration;
|
||||
|
||||
return new class extends Migration {
|
||||
public function up(): void
|
||||
{
|
||||
$checkoutForm = json_encode(self::getCheckoutFormSchema(), JSON_THROW_ON_ERROR);
|
||||
|
||||
$this->database->insert('telecart_forms', [
|
||||
'alias' => 'checkout',
|
||||
'friendly_name' => 'Оформление заказа',
|
||||
'schema' => $checkoutForm,
|
||||
'created_at' => Carbon::now(),
|
||||
'updated_at' => Carbon::now(),
|
||||
]);
|
||||
}
|
||||
|
||||
private static function getCheckoutFormSchema(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'id' => 'field_1_1763897608480',
|
||||
'$formkit' => 'text',
|
||||
'name' => 'firstname',
|
||||
'label' => 'Имя',
|
||||
'placeholder' => 'Например: Иван',
|
||||
'help' => 'Введите ваше имя',
|
||||
'validation' => 'required|length:0,32',
|
||||
'prefixIcon' => 'avatarMan',
|
||||
'locked' => true,
|
||||
],
|
||||
[
|
||||
'id' => 'field_2_1763897611020',
|
||||
'$formkit' => 'text',
|
||||
'name' => 'lastname',
|
||||
'label' => 'Фамилия',
|
||||
'placeholder' => 'Например: Иванов',
|
||||
'help' => 'Введите вашу фамилию',
|
||||
'validation' => 'required|length:0,32',
|
||||
'prefixIcon' => 'avatarMan',
|
||||
'locked' => true,
|
||||
],
|
||||
[
|
||||
'id' => 'field_5_1763897626036',
|
||||
'$formkit' => 'tel',
|
||||
'name' => 'telephone',
|
||||
'label' => 'Телефон',
|
||||
'placeholder' => 'Например: +7 (999) 000-00-00',
|
||||
'validation' => 'required|length:0,32',
|
||||
'help' => 'Введите ваш номер телефона.',
|
||||
'prefixIcon' => 'telephone',
|
||||
'locked' => true,
|
||||
],
|
||||
[
|
||||
'id' => 'field_4_1763897617570',
|
||||
'$formkit' => 'textarea',
|
||||
'name' => 'comment',
|
||||
'label' => 'Комментарий к заказу',
|
||||
'placeholder' => 'Например: Домофон не работает',
|
||||
'help' => 'Дополнительная информация к заказу',
|
||||
'validation' => 'length:0,5000',
|
||||
'locked' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
};
|
||||
@@ -66,6 +66,7 @@ class Container implements ContainerInterface
|
||||
* @return T
|
||||
* @psalm-param class-string<T>|string $id
|
||||
* @psalm-suppress MoreSpecificImplementedParamType
|
||||
*
|
||||
*/
|
||||
public function get(string $id)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,6 @@ use Openguru\OpenCartFramework\Container\Container;
|
||||
use Openguru\OpenCartFramework\Container\ServiceProvider;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Connections\ConnectionInterface;
|
||||
use Openguru\OpenCartFramework\Support\WorkLogsBag;
|
||||
|
||||
class MigrationsServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
||||
@@ -109,6 +109,7 @@ SQL;
|
||||
} catch (Exception $e) {
|
||||
$this->connection->rollbackTransaction();
|
||||
$this->logger->error("An error occurred while applying migration.", ['exception' => $e]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -455,4 +455,17 @@ class Builder
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function update(string $table, array $values): bool
|
||||
{
|
||||
$sql = $this->grammar->compileUpdate($this, $table, $values);
|
||||
|
||||
$bindings = array_merge(
|
||||
Utils::arrayFlatten($this->getBindings('join')),
|
||||
array_values($values),
|
||||
Utils::arrayFlatten($this->getBindings('where'))
|
||||
);
|
||||
|
||||
return $this->connection->statement($sql, $bindings);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,4 +201,25 @@ abstract class Grammar
|
||||
{
|
||||
return 'GROUP BY ' . implode(', ', $groupBy);
|
||||
}
|
||||
|
||||
public function compileUpdate(Builder $builder, string $table, array $values): string
|
||||
{
|
||||
$columns = [];
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
$columns[] = "`{$key}` = ?";
|
||||
}
|
||||
|
||||
$columns = implode(', ', $columns);
|
||||
|
||||
$joins = $this->compileJoins($builder, $builder->joins);
|
||||
|
||||
$joins = $joins ? ' ' . $joins : '';
|
||||
|
||||
$wheres = $this->compileWheres($builder, $builder->wheres);
|
||||
|
||||
$wheres = $wheres ? ' ' . $wheres : '';
|
||||
|
||||
return "UPDATE `{$table}`{$joins} SET {$columns}{$wheres}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,4 +206,20 @@ class Arr
|
||||
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает массив без указанных ключей.
|
||||
*
|
||||
* @param array $array Исходный массив
|
||||
* @param array $keys Массив ключей, которые нужно исключить
|
||||
* @return array Массив без исключенных ключей
|
||||
*/
|
||||
public static function except(array $array, array $keys): array
|
||||
{
|
||||
if (empty($keys)) {
|
||||
return $array;
|
||||
}
|
||||
|
||||
return array_diff_key($array, array_flip($keys));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
<env name="DB_DATABASE" value="ocstore3"/>
|
||||
<env name="DB_USERNAME" value="root"/>
|
||||
<env name="DB_PASSWORD" value="secret"/>
|
||||
<env name="DB_PORT" value="3306"/>
|
||||
<env name="DB_PREFIX" value="oc_"/>
|
||||
</php>
|
||||
</phpunit>
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App\Handlers;
|
||||
|
||||
use JsonException;
|
||||
use Openguru\OpenCartFramework\Exceptions\EntityNotFoundException;
|
||||
use Openguru\OpenCartFramework\Http\JsonResponse;
|
||||
use Openguru\OpenCartFramework\Http\Request;
|
||||
use Openguru\OpenCartFramework\Http\Response;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
|
||||
class FormsHandler
|
||||
{
|
||||
private Builder $builder;
|
||||
|
||||
public function __construct(Builder $builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws EntityNotFoundException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function getForm(Request $request): JsonResponse
|
||||
{
|
||||
$alias = $request->json('alias');
|
||||
if (! $alias) {
|
||||
return new JsonResponse([
|
||||
'error' => 'Form alias is required',
|
||||
], Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
$form = $this->builder->newQuery()
|
||||
->from('telecart_forms')
|
||||
->where('alias', '=', $alias)
|
||||
->firstOrNull();
|
||||
|
||||
if (! $form) {
|
||||
throw new EntityNotFoundException("Form with alias `{$alias}` not found");
|
||||
}
|
||||
|
||||
$schema = json_decode($form['schema'], true, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
return new JsonResponse([
|
||||
'data' => [
|
||||
'schema' => $schema,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ class ProductsHandler
|
||||
'message' => 'Product with id ' . $productId . ' not found',
|
||||
], Response::HTTP_NOT_FOUND);
|
||||
} catch (Exception $exception) {
|
||||
$this->logger->logException($exception);
|
||||
$this->logger->error($exception->getMessage(), ['exception' => $exception]);
|
||||
throw new RuntimeException('Error get product with id ' . $productId, 500);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ class TelegramHandler
|
||||
} catch (TelegramCommandNotFoundException $exception) {
|
||||
$this->telegramService->sendMessage($chatId, 'Неверная команда');
|
||||
} catch (Exception $exception) {
|
||||
$this->logger->logException($exception);
|
||||
$this->logger->error($exception->getMessage(), ['exception' => $exception]);
|
||||
}
|
||||
|
||||
return new JsonResponse([]);
|
||||
|
||||
@@ -4,16 +4,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Exceptions\OrderValidationFailedException;
|
||||
use DateTime;
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Openguru\OpenCartFramework\OpenCart\Decorators\OcRegistryDecorator;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Connections\ConnectionInterface;
|
||||
use Openguru\OpenCartFramework\Support\Arr;
|
||||
use Openguru\OpenCartFramework\Telegram\TelegramService;
|
||||
use Openguru\OpenCartFramework\Validator\ValidationRuleNotFoundException;
|
||||
use Openguru\OpenCartFramework\Validator\ValidatorInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
|
||||
class OrderCreateService
|
||||
@@ -24,7 +22,6 @@ class OrderCreateService
|
||||
private SettingsService $settings;
|
||||
private TelegramService $telegramService;
|
||||
private LoggerInterface $logger;
|
||||
private ValidatorInterface $validator;
|
||||
|
||||
public function __construct(
|
||||
ConnectionInterface $database,
|
||||
@@ -32,8 +29,7 @@ class OrderCreateService
|
||||
OcRegistryDecorator $registry,
|
||||
SettingsService $settings,
|
||||
TelegramService $telegramService,
|
||||
LoggerInterface $logger,
|
||||
ValidatorInterface $validator
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->database = $database;
|
||||
$this->cartService = $cartService;
|
||||
@@ -41,18 +37,11 @@ class OrderCreateService
|
||||
$this->settings = $settings;
|
||||
$this->telegramService = $telegramService;
|
||||
$this->logger = $logger;
|
||||
$this->validator = $validator;
|
||||
}
|
||||
|
||||
public function create(array $data, array $meta = []): array
|
||||
{
|
||||
try {
|
||||
$this->validate($data);
|
||||
} catch (ValidationRuleNotFoundException $e) {
|
||||
throw new RuntimeException($e->getMessage());
|
||||
}
|
||||
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$now = Carbon::now();
|
||||
$storeId = $this->settings->get('store.oc_store_id');
|
||||
$storeName = $this->settings->config()->getApp()->getAppName();
|
||||
$orderStatusId = $this->settings->config()->getOrders()->getOrderDefaultStatusId();
|
||||
@@ -70,12 +59,16 @@ class OrderCreateService
|
||||
$orderData = [
|
||||
'store_id' => $storeId,
|
||||
'store_name' => $storeName,
|
||||
'firstname' => $data['firstName'],
|
||||
'lastname' => $data['lastName'],
|
||||
'email' => $data['email'],
|
||||
'telephone' => $data['phone'],
|
||||
'comment' => $data['comment'],
|
||||
'shipping_address_1' => $data['address'],
|
||||
'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'] ?? '',
|
||||
@@ -93,7 +86,7 @@ class OrderCreateService
|
||||
$orderId = null;
|
||||
|
||||
$this->database->transaction(
|
||||
function () use (&$orderData, $products, $totals, $orderStatusId, $now, &$orderId) {
|
||||
function () use (&$orderData, $products, $totals, $orderStatusId, $now, &$orderId, $data) {
|
||||
$success = $this->database->insert(db_table('order'), $orderData);
|
||||
|
||||
if (! $success) {
|
||||
@@ -157,13 +150,14 @@ class OrderCreateService
|
||||
}
|
||||
|
||||
// Insert history
|
||||
$success = $this->database->insert(db_table('order_history'), [
|
||||
$history = [
|
||||
'order_id' => $orderId,
|
||||
'order_status_id' => $orderStatusId,
|
||||
'notify' => 0,
|
||||
'comment' => 'Заказ оформлен через Telegram Mini App',
|
||||
'comment' => $this->formatHistoryComment($data),
|
||||
'date_added' => $now,
|
||||
]);
|
||||
];
|
||||
$success = $this->database->insert(db_table('order_history'), $history);
|
||||
|
||||
if (! $success) {
|
||||
[, $error] = $this->database->getLastError();
|
||||
@@ -182,9 +176,9 @@ class OrderCreateService
|
||||
|
||||
$dateTimeFormatted = '';
|
||||
try {
|
||||
$dateTimeFormatted = (new DateTime($orderData['date_added']))->format('d.m.Y H:i');
|
||||
$dateTimeFormatted = $now->format('d.m.Y H:i');
|
||||
} catch (Exception $exception) {
|
||||
$this->logger->logException($exception);
|
||||
$this->logger->error($exception->getMessage(), ['exception' => $exception]);
|
||||
}
|
||||
|
||||
return [
|
||||
@@ -197,25 +191,6 @@ class OrderCreateService
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationRuleNotFoundException
|
||||
*/
|
||||
private function validate(array $data): void
|
||||
{
|
||||
$v = $this->validator->make($data, $this->makeValidationRulesFromSettings(), [
|
||||
'firstName' => 'Имя',
|
||||
'lastName' => 'Фамилия',
|
||||
'email' => 'E-mail',
|
||||
'phone' => 'Номер телефона',
|
||||
'address' => 'Адрес доставки',
|
||||
'comment' => 'Комментарий',
|
||||
]);
|
||||
|
||||
if ($v->fails()) {
|
||||
throw new OrderValidationFailedException($v->getErrors());
|
||||
}
|
||||
}
|
||||
|
||||
private function sendNotifications(array $orderData, array $tgInitData): void
|
||||
{
|
||||
$variables = [
|
||||
@@ -239,8 +214,10 @@ class OrderCreateService
|
||||
try {
|
||||
$this->telegramService->sendMessage((int) $chatId, $message);
|
||||
} catch (Exception $exception) {
|
||||
$this->logger->error("Telegram sendMessage to owner error. ChatID: $chatId, Message: $message");
|
||||
$this->logger->logException($exception);
|
||||
$this->logger->error(
|
||||
"Telegram sendMessage to owner error. ChatID: $chatId, Message: $message",
|
||||
['exception' => $exception],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,19 +230,38 @@ class OrderCreateService
|
||||
try {
|
||||
$this->telegramService->sendMessage($customerChatId, $message);
|
||||
} catch (Exception $exception) {
|
||||
$this->logger->error("Telegram sendMessage to customer error. ChatID: $chatId, Message: $message");
|
||||
$this->logger->logException($exception);
|
||||
$this->logger->error(
|
||||
"Telegram sendMessage to customer error. ChatID: $chatId, Message: $message",
|
||||
['exception' => $exception]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function makeValidationRulesFromSettings(): array
|
||||
private function formatHistoryComment(array $data): string
|
||||
{
|
||||
return [
|
||||
'firstName' => 'required',
|
||||
'lastName' => 'required',
|
||||
'phone' => 'required',
|
||||
'email' => 'email',
|
||||
];
|
||||
$customFields = Arr::except($data, [
|
||||
'firstname',
|
||||
'lastname',
|
||||
'email',
|
||||
'telephone',
|
||||
'comment',
|
||||
'shipping_address_1',
|
||||
'shipping_city',
|
||||
'shipping_zone',
|
||||
'shipping_postcode',
|
||||
'payment_method',
|
||||
'tgData',
|
||||
]);
|
||||
|
||||
$additionalString = '';
|
||||
if ($customFields) {
|
||||
$additionalString = "\n\nДополнительная информация по заказу:\n";
|
||||
foreach ($customFields as $field => $value) {
|
||||
$additionalString .= $field . ': ' . $value . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return "Заказ оформлен через Telegram Mini App.{$additionalString}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,7 +298,7 @@ class ProductsService
|
||||
'alt' => Utils::htmlEntityEncode($product_info['name']),
|
||||
];
|
||||
} catch (Exception $e) {
|
||||
$this->logger->logException($e);
|
||||
$this->logger->error($e->getMessage(), ['exception' => $e]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -391,6 +391,10 @@ class SettingsSerializerService
|
||||
}
|
||||
|
||||
if (isset($data['port'])) {
|
||||
if (is_string($data['port']) && ctype_digit($data['port'])) {
|
||||
$data['port'] = (int) $data['port'];
|
||||
}
|
||||
|
||||
if (! is_int($data['port'])) {
|
||||
throw new InvalidArgumentException('database.port must be an integer');
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ MARKDOWN;
|
||||
} catch (ClientException $exception) {
|
||||
$this->telegram->sendMessage($chatId, 'Ошибка: ' . $exception->getResponse()->getBody()->getContents());
|
||||
} catch (Throwable $exception) {
|
||||
$this->logger->logException($exception);
|
||||
$this->logger->error($exception->getMessage(), ['exception' => $exception]);
|
||||
$this->telegram->sendMessage($chatId, 'Произошла ошибка');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
|
||||
use App\Handlers\BannerHandler;
|
||||
use App\Handlers\BlocksHandler;
|
||||
use App\Handlers\CartHandler;
|
||||
use App\Handlers\CategoriesHandler;
|
||||
use App\Handlers\FiltersHandler;
|
||||
use App\Handlers\FormsHandler;
|
||||
use App\Handlers\HealthCheckHandler;
|
||||
use App\Handlers\OrderHandler;
|
||||
use App\Handlers\ProductsHandler;
|
||||
@@ -30,4 +30,6 @@ return [
|
||||
|
||||
'webhook' => [TelegramHandler::class, 'webhook'],
|
||||
'processBlock' => [BlocksHandler::class, 'processBlock'],
|
||||
|
||||
'getForm' => [FormsHandler::class, 'getForm'],
|
||||
];
|
||||
|
||||
@@ -44,25 +44,82 @@ class TestCase extends BaseTestCase
|
||||
private function bootstrapApplication(): Application
|
||||
{
|
||||
$app = ApplicationFactory::create([
|
||||
'database' => [
|
||||
'host' => getenv('DB_HOSTNAME') ?: 'mysql',
|
||||
'database' => getenv('DB_DATABASE') ?: 'ocstore3',
|
||||
'username' => getenv('DB_USERNAME') ?: 'root',
|
||||
'password' => getenv('DB_PASSWORD') ?: 'secret',
|
||||
'prefix' => getenv('DB_PREFIX') ?: 'oc_',
|
||||
'port' => getenv('DB_PORT') ?: 3306,
|
||||
'app' => [
|
||||
'app_enabled' => true,
|
||||
'app_name' => 'Telecart',
|
||||
'app_icon' => null,
|
||||
"theme_light" => "light",
|
||||
"theme_dark" => "dark",
|
||||
"app_debug" => false,
|
||||
'shop_base_url' => 'http://localhost', // for catalog: HTTPS_SERVER, for admin: HTTPS_CATALOG
|
||||
'language_id' => 10,
|
||||
],
|
||||
'logs' => [
|
||||
'path' => sys_get_temp_dir(),
|
||||
],
|
||||
'base_url' => 'http://localhost',
|
||||
'public_url' => 'http://localhost',
|
||||
|
||||
'telegram' => [
|
||||
'bot_token' => 'test_token',
|
||||
'chat_id' => '123',
|
||||
'owner_notification_template' => 'Test',
|
||||
'customer_notification_template' => 'Test',
|
||||
'mini_app_url' => 'https://example.com',
|
||||
"bot_token" => "",
|
||||
"chat_id" => null,
|
||||
"owner_notification_template" => 'owner_notification_template',
|
||||
"customer_notification_template" => 'customer_notification_template',
|
||||
"mini_app_url" => "",
|
||||
],
|
||||
|
||||
"metrics" => [
|
||||
"yandex_metrika_enabled" => false,
|
||||
"yandex_metrika_counter" => "",
|
||||
],
|
||||
|
||||
'store' => [
|
||||
'enable_store' => true,
|
||||
'feature_coupons' => true,
|
||||
'feature_vouchers' => true,
|
||||
'oc_store_id' => 777,
|
||||
'oc_default_currency' => 'RRR',
|
||||
'oc_config_tax' => true,
|
||||
],
|
||||
|
||||
'texts' => [
|
||||
'text_no_more_products' => 'Это всё по текущему запросу. Попробуйте уточнить фильтры или поиск.',
|
||||
'text_empty_cart' => 'Ваша корзина пуста.',
|
||||
'text_order_created_success' => 'Ваш заказ успешно оформлен и будет обработан в ближайшее время.'
|
||||
],
|
||||
|
||||
'orders' => [
|
||||
'order_default_status_id' => 11,
|
||||
'oc_customer_group_id' => 99,
|
||||
],
|
||||
|
||||
'mainpage_blocks' => [
|
||||
[
|
||||
'type' => 'products_feed',
|
||||
'title' => '',
|
||||
'description' => '',
|
||||
'is_enabled' => true,
|
||||
'goal_name' => '',
|
||||
'data' => [
|
||||
'max_page_count' => 10,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
'cache' => [
|
||||
'namespace' => 'telecart',
|
||||
'default_lifetime' => 60 * 60 * 24,
|
||||
'options' => [
|
||||
'db_table' => 'telecart_cache_items',
|
||||
],
|
||||
],
|
||||
|
||||
'logs' => [
|
||||
'path' => '/tmp'
|
||||
],
|
||||
|
||||
'database' => [
|
||||
'host' => env('DB_HOSTNAME'),
|
||||
'database' => env('DB_DATABASE'),
|
||||
'username' => env('DB_USERNAME'),
|
||||
'password' => env('DB_PASSWORD'),
|
||||
'prefix' => env('DB_PREFIX') ?: 'oc_',
|
||||
'port' => env('DB_PORT'),
|
||||
],
|
||||
]);
|
||||
|
||||
|
||||
@@ -663,4 +663,34 @@ class ArrTest extends TestCase
|
||||
|
||||
$this->assertSame([], $result);
|
||||
}
|
||||
|
||||
public function testExceptRemovesSpecifiedKeys(): void
|
||||
{
|
||||
$array = [
|
||||
'app' => 'telecart',
|
||||
'debug' => true,
|
||||
'version' => '1.0.0',
|
||||
];
|
||||
|
||||
$result = Arr::except($array, ['debug', 'nonexistent']);
|
||||
|
||||
$expected = [
|
||||
'app' => 'telecart',
|
||||
'version' => '1.0.0',
|
||||
];
|
||||
|
||||
$this->assertSame($expected, $result);
|
||||
}
|
||||
|
||||
public function testExceptReturnsOriginalArrayWhenNoKeysProvided(): void
|
||||
{
|
||||
$array = [
|
||||
'app' => 'telecart',
|
||||
'debug' => true,
|
||||
];
|
||||
|
||||
$result = Arr::except($array, []);
|
||||
|
||||
$this->assertSame($array, $result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,4 +512,92 @@ class BuilderTest extends TestCase
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public function testUpdate(): void
|
||||
{
|
||||
$connection = $this->createMock(MySqlConnection::class);
|
||||
$connection->expects($this->once())
|
||||
->method('statement')
|
||||
->with(
|
||||
'UPDATE `telecart_settings` SET `alias` = ?, `foo` = ? WHERE alias = ?',
|
||||
['foobar2', 'bar2', 'foobar']
|
||||
)
|
||||
->willReturn(true);
|
||||
|
||||
$builder = new Builder($connection, new MySqlGrammar());
|
||||
|
||||
$builder->newQuery()
|
||||
->where('alias', '=', 'foobar')
|
||||
->update('telecart_settings', [
|
||||
'alias' => 'foobar2',
|
||||
'foo' => 'bar2',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testUpdateJsonField(): void
|
||||
{
|
||||
$json = json_encode(['xyz' => 'bazz'], JSON_THROW_ON_ERROR);
|
||||
|
||||
$connection = $this->createMock(MySqlConnection::class);
|
||||
$connection->expects($this->once())
|
||||
->method('statement')
|
||||
->with(
|
||||
'UPDATE `telecart_settings` SET `json` = ? WHERE alias = ?',
|
||||
[$json, 'foobar']
|
||||
)
|
||||
->willReturn(true);
|
||||
|
||||
$builder = new Builder($connection, new MySqlGrammar());
|
||||
|
||||
$builder->newQuery()
|
||||
->where('alias', '=', 'foobar')
|
||||
->update('telecart_settings', [
|
||||
'json' => $json,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testUpdateJsonFieldWithCyrillic(): void
|
||||
{
|
||||
$json = json_encode(['xyz' => 'привет'], JSON_THROW_ON_ERROR);
|
||||
|
||||
$connection = $this->createMock(MySqlConnection::class);
|
||||
$connection->expects($this->once())
|
||||
->method('statement')
|
||||
->with(
|
||||
'UPDATE `telecart_settings` SET `json` = ? WHERE alias = ?',
|
||||
[$json, 'foobar']
|
||||
)
|
||||
->willReturn(true);
|
||||
|
||||
$builder = new Builder($connection, new MySqlGrammar());
|
||||
|
||||
$builder->newQuery()
|
||||
->where('alias', '=', 'foobar')
|
||||
->update('telecart_settings', [
|
||||
'json' => $json,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testUpdateWithJoin(): void
|
||||
{
|
||||
$connection = $this->createMock(MySqlConnection::class);
|
||||
$connection->expects($this->once())
|
||||
->method('statement')
|
||||
->with(
|
||||
'UPDATE `t1` INNER JOIN t2 ON t1.id = t2.t1_id SET `t1.foo` = ? WHERE t2.bar = ?',
|
||||
['new_value', 'condition']
|
||||
)
|
||||
->willReturn(true);
|
||||
|
||||
$builder = new Builder($connection, new MySqlGrammar());
|
||||
|
||||
$builder->newQuery()
|
||||
->join('t2', function (JoinClause $join) {
|
||||
$join->on('t1.id', '=', 't2.t1_id');
|
||||
})
|
||||
->where('t2.bar', '=', 'condition')
|
||||
->update('t1', [
|
||||
't1.foo' => 'new_value',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ class HelpersTest extends TestCase
|
||||
{
|
||||
public function testDbTable(): void
|
||||
{
|
||||
|
||||
$this->assertEquals('oc_some_table', db_table('some_table'));
|
||||
}
|
||||
|
||||
|
||||
@@ -230,4 +230,52 @@ class MySqlGrammarTest extends TestCase
|
||||
$this->grammar->compileGroupBy($mock, ['foo', 'bar'])
|
||||
);
|
||||
}
|
||||
|
||||
public function testCompileUpdate(): void
|
||||
{
|
||||
$builder = m::mock(Builder::class);
|
||||
$builder->joins = [];
|
||||
$builder->wheres = [
|
||||
[
|
||||
'type' => 'Basic',
|
||||
'column' => 'id',
|
||||
'operator' => '=',
|
||||
'value' => 1,
|
||||
'boolean' => 'and',
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertEquals(
|
||||
"UPDATE `table` SET `foo` = ?, `bar` = ? WHERE id = ?",
|
||||
$this->grammar->compileUpdate($builder, 'table', ['foo' => 'bar', 'bar' => 'baz'])
|
||||
);
|
||||
}
|
||||
|
||||
public function testCompileUpdateWithJoins(): void
|
||||
{
|
||||
$joinClause = m::mock(JoinClause::class);
|
||||
$joinClause->table = 'other_table';
|
||||
$joinClause->type = 'inner';
|
||||
$joinClause->first = 'table.id';
|
||||
$joinClause->operator = '=';
|
||||
$joinClause->second = 'other_table.id';
|
||||
$joinClause->wheres = [];
|
||||
|
||||
$builder = m::mock(Builder::class);
|
||||
$builder->joins = [$joinClause];
|
||||
$builder->wheres = [
|
||||
[
|
||||
'type' => 'Basic',
|
||||
'column' => 'table.id',
|
||||
'operator' => '=',
|
||||
'value' => 1,
|
||||
'boolean' => 'and',
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertEquals(
|
||||
"UPDATE `table` INNER JOIN other_table ON table.id = other_table.id SET `foo` = ?, `bar` = ? WHERE table.id = ?",
|
||||
$this->grammar->compileUpdate($builder, 'table', ['foo' => 'bar', 'bar' => 'baz'])
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit\Services;
|
||||
|
||||
use App\Services\CartService;
|
||||
use App\Services\OrderCreateService;
|
||||
use App\Services\SettingsService;
|
||||
use Carbon\Carbon;
|
||||
use Mockery as m;
|
||||
use Openguru\OpenCartFramework\OpenCart\Decorators\OcRegistryDecorator;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Connections\ConnectionInterface;
|
||||
use Openguru\OpenCartFramework\Telegram\TelegramService;
|
||||
use Openguru\OpenCartFramework\Validator\ValidatorInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Tests\TestCase;
|
||||
|
||||
class OrderCreateServiceTest extends TestCase
|
||||
{
|
||||
public function testCreateNewOrder(): void
|
||||
{
|
||||
$data = [
|
||||
'firstname' => 'John',
|
||||
'lastname' => 'Doe',
|
||||
'email' => 'test@mail.com',
|
||||
'telephone' => '+79999999999',
|
||||
'comment' => 'Comment',
|
||||
'shipping_address_1' => 'Russia, Moscow',
|
||||
'shipping_city' => 'Moscow',
|
||||
'shipping_zone' => 'Rostov',
|
||||
'shipping_postcode' => 'Rostov',
|
||||
'payment_method' => 'Cash',
|
||||
'field_1' => 'кирилица',
|
||||
'field_2' => 'hello',
|
||||
'tgData' => [],
|
||||
];
|
||||
|
||||
$meta = [
|
||||
'ip' => '127.0.0.1',
|
||||
'user_agent' => 'UnitTests',
|
||||
];
|
||||
|
||||
$dateAdded = '2026-01-01 00:00:00';
|
||||
$dateAddedFormatted = '01.01.2026 00:00';
|
||||
Carbon::setTestNow($dateAdded);
|
||||
$totalText = '100.5р.';
|
||||
$totalNumeric = 100.5;
|
||||
$totals = [];
|
||||
$currencyId = 100;
|
||||
$currencyCode = $this->app->getConfigValue('store.oc_default_currency');
|
||||
$currencyValue = 222;
|
||||
$orderId = 1111;
|
||||
$orderProductId = 223;
|
||||
|
||||
$product = [
|
||||
'product_id' => 93,
|
||||
'name' => 'Product Name',
|
||||
'model' => 'Product Model',
|
||||
'quantity' => 1,
|
||||
'price_numeric' => 100,
|
||||
'total_numeric' => 100,
|
||||
'reward_numeric' => 88,
|
||||
];
|
||||
$products = [$product];
|
||||
|
||||
$connection = m::mock(ConnectionInterface::class);
|
||||
$connection->shouldReceive('transaction')->once()->andReturnUsing(fn($c) => $c());
|
||||
$connection->shouldReceive('lastInsertId')->once()->andReturn($orderId)->ordered();
|
||||
$connection->shouldReceive('lastInsertId')->once()->andReturn($orderProductId)->ordered();
|
||||
|
||||
$connection->shouldReceive('insert')->once()->with(
|
||||
db_table('order'),
|
||||
[
|
||||
'store_id' => $this->app->getConfigValue('store.oc_store_id'),
|
||||
'store_name' => $this->app->getConfigValue('app.app_name'),
|
||||
'firstname' => $data['firstname'],
|
||||
'lastname' => $data['lastname'],
|
||||
'email' => $data['email'],
|
||||
'telephone' => $data['telephone'],
|
||||
'payment_method' => $data['payment_method'],
|
||||
'comment' => $data['comment'],
|
||||
'shipping_address_1' => $data['shipping_address_1'],
|
||||
'shipping_city' => $data['shipping_city'],
|
||||
'shipping_zone' => $data['shipping_zone'],
|
||||
'shipping_postcode' => $data['shipping_postcode'],
|
||||
'total' => $totalNumeric,
|
||||
'order_status_id' => $this->app->getConfigValue('orders.order_default_status_id'),
|
||||
'ip' => $meta['ip'],
|
||||
'forwarded_ip' => $meta['ip'],
|
||||
'user_agent' => $meta['user_agent'],
|
||||
'date_added' => $dateAdded,
|
||||
'date_modified' => $dateAdded,
|
||||
'language_id' => $this->app->getConfigValue('app.language_id'),
|
||||
'currency_id' => $currencyId,
|
||||
'currency_code' => $currencyCode,
|
||||
'currency_value' => $currencyValue,
|
||||
'customer_group_id' => $this->app->getConfigValue('orders.oc_customer_group_id'),
|
||||
],
|
||||
)
|
||||
->andReturn(true);
|
||||
|
||||
$connection->shouldReceive('insert')->once()->with(
|
||||
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'],
|
||||
]
|
||||
)->andReturn(true);
|
||||
|
||||
$connection->shouldReceive('insert')->once()->with(
|
||||
db_table('order_history'),
|
||||
[
|
||||
'order_id' => $orderId,
|
||||
'order_status_id' => $this->app->getConfigValue('orders.order_default_status_id'),
|
||||
'notify' => 0,
|
||||
'comment' => 'Заказ оформлен через Telegram Mini App.'
|
||||
. "\n\nДополнительная информация по заказу:"
|
||||
. "\nfield_1: кирилица"
|
||||
. "\nfield_2: hello\n",
|
||||
'date_added' => $dateAdded,
|
||||
],
|
||||
)->andReturnTrue();
|
||||
|
||||
$cartService = m::mock(CartService::class);
|
||||
$cartService
|
||||
->shouldReceive('getCart')
|
||||
->once()
|
||||
->andReturn([
|
||||
'total' => $totalNumeric,
|
||||
'totals' => $totals,
|
||||
'products' => $products,
|
||||
'total_text' => $totalText,
|
||||
]);
|
||||
|
||||
$cartService->shouldReceive('flush')->once()->andReturnNull();
|
||||
|
||||
$ocCurrencyMock = m::mock();
|
||||
$ocCurrencyMock->shouldReceive('getId')->once()->andReturn($currencyId);
|
||||
$ocCurrencyMock->shouldReceive('getValue')->once()->andReturn($currencyValue);
|
||||
$ocSessionMock = m::mock();
|
||||
$ocSessionMock->data = [
|
||||
'currency' => $currencyCode,
|
||||
];
|
||||
|
||||
$registryMock = m::mock('Registry');
|
||||
$registryMock->shouldReceive('get')->with('currency')->andReturn($ocCurrencyMock);
|
||||
$registryMock->shouldReceive('get')->with('session')->andReturn($ocSessionMock);
|
||||
$ocRegistryDecorator = new OcRegistryDecorator($registryMock);
|
||||
|
||||
$telegramServiceMock = m::mock(TelegramService::class);
|
||||
$loggerMock = m::mock(LoggerInterface::class);
|
||||
$validatorMock = m::mock(ValidatorInterface::class);
|
||||
|
||||
$service = new OrderCreateService(
|
||||
$connection,
|
||||
$cartService,
|
||||
$ocRegistryDecorator,
|
||||
$this->app->get(SettingsService::class),
|
||||
$telegramServiceMock,
|
||||
$loggerMock,
|
||||
$validatorMock,
|
||||
);
|
||||
|
||||
$order = $service->create($data, $meta);
|
||||
|
||||
$this->assertEquals([
|
||||
'id' => $orderId,
|
||||
'created_at' => $dateAddedFormatted,
|
||||
'total' => $totalText,
|
||||
'final_total_numeric' => $totalNumeric,
|
||||
'currency' => $currencyCode,
|
||||
'products' => $products,
|
||||
], $order);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user