Псевдоанонимные идентификаторы аккаунтов и комментарий к заказу
This commit is contained in:
parent
ada91bd0b7
commit
0a8c74a9a3
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\commands;
|
||||||
|
|
||||||
|
use yii\console\Controller;
|
||||||
|
use yii\console\ExitCode;
|
||||||
|
|
||||||
|
use app\models\Account;
|
||||||
|
|
||||||
|
class AccountController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Сгенерировать уникальные идентификаторы
|
||||||
|
*
|
||||||
|
* @param int|string $_key Ключ аккаунта (оставить пустым или отправить "all", если для всех)
|
||||||
|
* @param bool $init Параметр обозначающий изменение только для тех у кого ранее идентификатор задан не был (без перезаписи)
|
||||||
|
*/
|
||||||
|
public function actionGenerateIndex(int|string $_key = null, bool $init = true)
|
||||||
|
{
|
||||||
|
// Инициализация
|
||||||
|
$accounts = empty($_key) || strcasecmp($_key, 'all') === 0 ? Account::readAll() : [Account::searchById($_key)];
|
||||||
|
|
||||||
|
// Генерация
|
||||||
|
$amount = Account::generateIndexes($accounts, $init);
|
||||||
|
|
||||||
|
echo 'Обработано аккаунтов: ' . $amount;
|
||||||
|
|
||||||
|
if ($amount > 0) {
|
||||||
|
// Был успешно обработан минимум 1 аккаунт
|
||||||
|
|
||||||
|
return ExitCode::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExitCode::UNSPECIFIED_ERROR;
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,10 @@ use app\models\connection\Dellin;
|
||||||
|
|
||||||
class DellinController extends Controller
|
class DellinController extends Controller
|
||||||
{
|
{
|
||||||
public function actionCitiesImport()
|
/**
|
||||||
|
* Импортировать города из ДеловыеЛинии
|
||||||
|
*/
|
||||||
|
public function actionImportCities()
|
||||||
{
|
{
|
||||||
if (Dellin::importCities()) {
|
if (Dellin::importCities()) {
|
||||||
return ExitCode::OK;
|
return ExitCode::OK;
|
||||||
|
@ -17,4 +20,16 @@ class DellinController extends Controller
|
||||||
|
|
||||||
return ExitCode::UNSPECIFIED_ERROR;
|
return ExitCode::UNSPECIFIED_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Импортировать терминалы из ДеловыеЛинии
|
||||||
|
*/
|
||||||
|
public function actionImportTerminals()
|
||||||
|
{
|
||||||
|
if (Dellin::importTerminals()) {
|
||||||
|
return ExitCode::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExitCode::UNSPECIFIED_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,14 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace app\controllers;
|
namespace app\controllers;
|
||||||
|
|
||||||
|
use app\models\Notification;
|
||||||
use yii;
|
use yii;
|
||||||
use yii\filters\AccessControl;
|
use yii\filters\AccessControl;
|
||||||
use yii\web\Controller;
|
use yii\web\Controller;
|
||||||
use yii\web\Response;
|
use yii\web\Response;
|
||||||
|
|
||||||
use app\models\Order;
|
use app\models\Order;
|
||||||
|
use app\models\OrderEdgeSupply;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
|
@ -24,7 +26,7 @@ class CartController extends Controller
|
||||||
{
|
{
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$page = yii::$app->request->get('page') ?? yii::$app->request->post('page') ?? 1;
|
$page = yii::$app->request->get('page') ?? yii::$app->request->post('page') ?? 1;
|
||||||
$account = yii::$app->user;
|
$account = yii::$app->user->identity;
|
||||||
|
|
||||||
// Поиск корзины (текущего заказа)
|
// Поиск корзины (текущего заказа)
|
||||||
$model = Order::search();
|
$model = Order::search();
|
||||||
|
@ -41,7 +43,7 @@ class CartController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
// Инициализация содержимого корзины
|
// Инициализация содержимого корзины
|
||||||
$supplies = $model->content(10, $page);
|
$connections = $model->content(10, $page);
|
||||||
|
|
||||||
if (yii::$app->request->isPost) {
|
if (yii::$app->request->isPost) {
|
||||||
// POST-запрос
|
// POST-запрос
|
||||||
|
@ -49,13 +51,88 @@ class CartController extends Controller
|
||||||
yii::$app->response->format = Response::FORMAT_JSON;
|
yii::$app->response->format = Response::FORMAT_JSON;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'main' => $this->renderPartial('index', compact('model', 'supplies')),
|
'main' => $this->renderPartial('index', compact('model', 'connections')),
|
||||||
'title' => 'Корзина',
|
'title' => 'Корзина',
|
||||||
'redirect' => '/cart',
|
'redirect' => '/cart',
|
||||||
'_csrf' => yii::$app->request->getCsrfToken()
|
'_csrf' => yii::$app->request->getCsrfToken()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->render('index', compact('model', 'supplies'));
|
return $this->render('index', compact('model', 'connections'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function actionEditComm(string $catn): array|string|null
|
||||||
|
{
|
||||||
|
// Инициализация
|
||||||
|
$return = [
|
||||||
|
'_csrf' => yii::$app->request->getCsrfToken()
|
||||||
|
];
|
||||||
|
|
||||||
|
if (is_null($catn)) {
|
||||||
|
// Не получен артикул
|
||||||
|
|
||||||
|
yii::$app->response->statusCode = 500;
|
||||||
|
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($edges = OrderEdgeSupply::searchBySupplyCatn($catn)) {
|
||||||
|
// Рёбра найдены (связи заказа с поставкой)
|
||||||
|
|
||||||
|
// Инициализация
|
||||||
|
$amount = 0;
|
||||||
|
|
||||||
|
foreach ($edges as $edge) {
|
||||||
|
// Перебор рёбер (связей заказа с поставкой)
|
||||||
|
|
||||||
|
// Инициализация
|
||||||
|
$text = yii::$app->request->post('text') ?? yii::$app->request->get('text') ?? 'Комментарий к заказу';
|
||||||
|
|
||||||
|
$comm = $edge->comm ?? null;
|
||||||
|
$edge->comm = $text;
|
||||||
|
|
||||||
|
if ($edge->save()) {
|
||||||
|
// Ребро обновлено
|
||||||
|
|
||||||
|
// Запись в журнал
|
||||||
|
$edge->journal('update', ['comm' => ['from' => $comm, 'to' => $edge->comm]]);
|
||||||
|
|
||||||
|
// Обновление счётчика
|
||||||
|
++$amount;
|
||||||
|
|
||||||
|
// Запись в буфер ответа
|
||||||
|
$return['comm'] = $text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($amount > 0) {
|
||||||
|
// Удалось записать минимум 1 связь с поставкой
|
||||||
|
|
||||||
|
Notification::_write("Обновлён комментарий к товару $catn ($amount шт)");
|
||||||
|
} else {
|
||||||
|
// Не удалось записать минимум 1 связь с поставкой
|
||||||
|
|
||||||
|
Notification::_write("Не удалось обновить комментарий к товару $catn");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Конец алгоритма
|
||||||
|
*/
|
||||||
|
end:
|
||||||
|
|
||||||
|
if (yii::$app->request->isPost) {
|
||||||
|
// POST-запрос
|
||||||
|
|
||||||
|
yii::$app->response->format = Response::FORMAT_JSON;
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($model = Product::searchByCatn($catn)) {
|
||||||
|
return $this->render('index', compact('model'));
|
||||||
|
} else {
|
||||||
|
return $this->redirect('/');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ class NotificationController extends Controller
|
||||||
* @param bool $new Активация проверки на то, что уведомление не получено
|
* @param bool $new Активация проверки на то, что уведомление не получено
|
||||||
* @param bool $count Посчитать
|
* @param bool $count Посчитать
|
||||||
*/
|
*/
|
||||||
$search = function (bool $new = false, bool $count = false) use ($model, $account, $type, $let, $limit): array|int|null {
|
$search = function (bool $new = false, bool $count = false) use ($model, $account, $type, $let, $limit): array|int|null|Notification {
|
||||||
if ($count) {
|
if ($count) {
|
||||||
// Запрошен подсчёт непрочитанных уведомлений
|
// Запрошен подсчёт непрочитанных уведомлений
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ class NotificationController extends Controller
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($notifications as $notification) {
|
foreach (is_array($notifications) ? $notifications : [$notifications] as $notification) {
|
||||||
// Перебор найденных уведомлений
|
// Перебор найденных уведомлений
|
||||||
|
|
||||||
if ($preload) {
|
if ($preload) {
|
||||||
|
@ -174,7 +174,7 @@ class NotificationController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
// Запись ребра: ПОЛЬЗОВАТЕЛЬ -> УВЕДОМЛЕНИЕ (о том, что уведомление прочитано)
|
// Запись ребра: ПОЛЬЗОВАТЕЛЬ -> УВЕДОМЛЕНИЕ (о том, что уведомление прочитано)
|
||||||
AccountEdgeNotification::write(yii::$app->user->id, $notification->readId(), $type);
|
AccountEdgeNotification::write($account->readId(), $notification->readId(), $type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yii::$app->request->post('last')) {
|
if (yii::$app->request->post('last')) {
|
||||||
|
|
|
@ -96,7 +96,7 @@ class OrderController extends Controller
|
||||||
// POST-запрос
|
// POST-запрос
|
||||||
|
|
||||||
// Инициализация входных данных
|
// Инициализация входных данных
|
||||||
$account = yii::$app->user;
|
$account = yii::$app->user->identity;
|
||||||
$supplies = yii::$app->request->post('supplies');
|
$supplies = yii::$app->request->post('supplies');
|
||||||
|
|
||||||
yii::$app->response->format = Response::FORMAT_JSON;
|
yii::$app->response->format = Response::FORMAT_JSON;
|
||||||
|
@ -122,7 +122,7 @@ class OrderController extends Controller
|
||||||
$model->save() or throw new Exception('Не удалось инициализировать заказ');
|
$model->save() or throw new Exception('Не удалось инициализировать заказ');
|
||||||
|
|
||||||
// Запись ребра: АККАУНТ -> ЗАКАЗ
|
// Запись ребра: АККАУНТ -> ЗАКАЗ
|
||||||
AccountEdgeOrder::write($account->id, $model->readId(), 'current') or $model->addError('errors', 'Не удалось инициализировать ребро: АККАУНТ -> ЗАКАЗ');
|
AccountEdgeOrder::write($account->readId(), $model->readId(), 'current') or $model->addError('errors', 'Не удалось инициализировать ребро: АККАУНТ -> ЗАКАЗ');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверка входных данных
|
// Проверка входных данных
|
||||||
|
@ -155,7 +155,7 @@ class OrderController extends Controller
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$targets = yii::$app->request->post('targets') ?? yii::$app->request->get('targets');
|
$targets = yii::$app->request->post('targets') ?? yii::$app->request->get('targets');
|
||||||
$page = yii::$app->request->get('page') ?? yii::$app->request->post('page') ?? 1;
|
$page = yii::$app->request->get('page') ?? yii::$app->request->post('page') ?? 1;
|
||||||
$account = yii::$app->user;
|
$account = yii::$app->user->identity;
|
||||||
$order = Order::search();
|
$order = Order::search();
|
||||||
|
|
||||||
if ($targets) {
|
if ($targets) {
|
||||||
|
@ -182,7 +182,7 @@ class OrderController extends Controller
|
||||||
$order->journal('reserved');
|
$order->journal('reserved');
|
||||||
|
|
||||||
// Поиск
|
// Поиск
|
||||||
$edge = AccountEdgeOrder::searchByVertex($account->id, $order->readId(), 'current');
|
$edge = AccountEdgeOrder::searchByVertex($account->readId(), $order->readId(), 'current');
|
||||||
|
|
||||||
if (count($edge) > 1) {
|
if (count($edge) > 1) {
|
||||||
// Найден более чем 1 заказ
|
// Найден более чем 1 заказ
|
||||||
|
@ -214,7 +214,7 @@ class OrderController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
// Инициализация содержимого корзины
|
// Инициализация содержимого корзины
|
||||||
$supplies = $order->content(10, $page);
|
$connections = $order->content(10, $page);
|
||||||
|
|
||||||
if (yii::$app->request->isPost) {
|
if (yii::$app->request->isPost) {
|
||||||
// POST-запрос
|
// POST-запрос
|
||||||
|
@ -222,14 +222,14 @@ class OrderController extends Controller
|
||||||
yii::$app->response->format = Response::FORMAT_JSON;
|
yii::$app->response->format = Response::FORMAT_JSON;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'main' => $this->renderPartial('/cart/index', compact('order', 'supplies')),
|
'main' => $this->renderPartial('/cart/index', compact('order', 'connections')),
|
||||||
'title' => 'Корзина',
|
'title' => 'Корзина',
|
||||||
'redirect' => '/cart',
|
'redirect' => '/cart',
|
||||||
'_csrf' => yii::$app->request->getCsrfToken()
|
'_csrf' => yii::$app->request->getCsrfToken()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->render('/cart/index', compact('order', 'supplies'));
|
return $this->render('/cart/index', compact('order', 'connections'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -242,7 +242,7 @@ class OrderController extends Controller
|
||||||
$page = yii::$app->request->get('page') ?? yii::$app->request->post('page') ?? 1;
|
$page = yii::$app->request->get('page') ?? yii::$app->request->post('page') ?? 1;
|
||||||
$account = yii::$app->user;
|
$account = yii::$app->user;
|
||||||
$order = Order::search();
|
$order = Order::search();
|
||||||
$supplies = $order->content(10, $page);
|
$connections = $order->content(10, $page);
|
||||||
|
|
||||||
foreach (isset($targets[0]) && is_array($targets[0]) ? $targets : [$targets] as $target) {
|
foreach (isset($targets[0]) && is_array($targets[0]) ? $targets : [$targets] as $target) {
|
||||||
// Унификация входных параметров
|
// Унификация входных параметров
|
||||||
|
@ -250,22 +250,22 @@ class OrderController extends Controller
|
||||||
foreach ($target as $catn => $amount) {
|
foreach ($target as $catn => $amount) {
|
||||||
// Перебор целей (переданных объектов в корзине)
|
// Перебор целей (переданных объектов в корзине)
|
||||||
|
|
||||||
foreach ($supplies as $supply) {
|
foreach ($connections as $connection) {
|
||||||
// Перебор объектов в корзине
|
// Перебор объектов в корзине
|
||||||
|
|
||||||
if ($supply->catn === $catn) {
|
if ($connection['supply']['catn'] === $catn) {
|
||||||
// Цель найдена
|
// Цель найдена
|
||||||
|
|
||||||
if ($supply->amnt > $amount) {
|
if ($connection['amount'] > $amount) {
|
||||||
// Запрошено уменьшение количества
|
// Запрошено уменьшение количества
|
||||||
|
|
||||||
// Удаление
|
// Удаление
|
||||||
$order->deleteSupply([$catn => $supply->amnt - $amount]);
|
$order->deleteSupply([$catn => $connection['amount'] - $amount]);
|
||||||
} else if ($supply->amnt < $amount) {
|
} else if ($connection['amount'] < $amount) {
|
||||||
// Запрошено увеличение количества
|
// Запрошено увеличение количества
|
||||||
|
|
||||||
// Запись
|
// Запись
|
||||||
$order->writeSupply([$supply->catn => $amount - $supply->amnt]);
|
$order->writeSupply([$connection['supply']['catn'] => $amount - $connection['amount']]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,7 +273,7 @@ class OrderController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ренициализация
|
// Ренициализация
|
||||||
$supplies = $order->content(10, $page);
|
$connections = $order->content(10, $page);
|
||||||
|
|
||||||
if (yii::$app->request->isPost) {
|
if (yii::$app->request->isPost) {
|
||||||
// POST-запрос
|
// POST-запрос
|
||||||
|
@ -281,14 +281,14 @@ class OrderController extends Controller
|
||||||
yii::$app->response->format = Response::FORMAT_JSON;
|
yii::$app->response->format = Response::FORMAT_JSON;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'main' => $this->renderPartial('/cart/index', compact('order', 'supplies')),
|
'main' => $this->renderPartial('/cart/index', compact('order', 'connections')),
|
||||||
'title' => 'Корзина',
|
'title' => 'Корзина',
|
||||||
'redirect' => '/cart',
|
'redirect' => '/cart',
|
||||||
'_csrf' => yii::$app->request->getCsrfToken()
|
'_csrf' => yii::$app->request->getCsrfToken()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->render('/cart/index', compact('order', 'supplies'));
|
return $this->render('/cart/index', compact('order', 'connections'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -208,7 +208,6 @@ class ProductController extends Controller
|
||||||
|
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$text = yii::$app->request->post('text') ?? yii::$app->request->get('text') ?? '0';
|
$text = yii::$app->request->post('text') ?? yii::$app->request->get('text') ?? '0';
|
||||||
$text or $text = '0';
|
|
||||||
$dimension = yii::$app->request->post('dimension') ?? yii::$app->request->get('dimension') ?? 'x';
|
$dimension = yii::$app->request->post('dimension') ?? yii::$app->request->get('dimension') ?? 'x';
|
||||||
|
|
||||||
$product->dmns = array_merge(
|
$product->dmns = array_merge(
|
||||||
|
@ -265,8 +264,6 @@ class ProductController extends Controller
|
||||||
|
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$text = yii::$app->request->post('text') ?? yii::$app->request->get('text') ?? '0';
|
$text = yii::$app->request->post('text') ?? yii::$app->request->get('text') ?? '0';
|
||||||
$text or $text = '0';
|
|
||||||
|
|
||||||
$product->wght = $text;
|
$product->wght = $text;
|
||||||
|
|
||||||
if ($product->save()) {
|
if ($product->save()) {
|
||||||
|
|
|
@ -12,6 +12,8 @@ use app\models\Product;
|
||||||
use app\models\Supply;
|
use app\models\Supply;
|
||||||
use app\models\Search;
|
use app\models\Search;
|
||||||
|
|
||||||
|
use app\models\connection\Dellin;
|
||||||
|
|
||||||
class SearchController extends Controller
|
class SearchController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -167,9 +169,19 @@ class SearchController extends Controller
|
||||||
$row['overload'] = true;
|
$row['overload'] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Поиск аккаунтов владельцев поставок
|
|
||||||
foreach ($row['supplies'] as &$edge) {
|
foreach ($row['supplies'] as &$edge) {
|
||||||
|
// Перебор поставок
|
||||||
|
|
||||||
|
// Инициализация аккаунта
|
||||||
$edge['account'] = Supply::searchAccountById($edge['_from']);
|
$edge['account'] = Supply::searchAccountById($edge['_from']);
|
||||||
|
|
||||||
|
// Инициализация доставки
|
||||||
|
$edge['delivery'] = Dellin::calcDelivery($edge['account']['opts']['delivery_from_city'] ?? $settings['delivery_from_city_default'] ?? '2700000100000000000000000', yii::$app->user->identity->opts['delivery_to_city'] ?? $settings['delivery_to_city_default'] ?? '2700000100000000000000000')['terminals_standard'];
|
||||||
|
$edge['delivery']['max'] = $edge['delivery']['period_to'];
|
||||||
|
$edge['delivery']['price'] = $edge['delivery']['price'];
|
||||||
|
|
||||||
|
// Инициализация цены (цена поставки + цена доставки + наша наценка)
|
||||||
|
$edge['prce'] = ($edge['prce'] ?? $edge['onec']['Цены']['Цена']['ЦенаЗаЕдиницу']) + ($edge['delivery']['price'] ?? 0) + ($settings['increase'] ?? 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ class Account extends Document implements IdentityInterface, PartnerInterface
|
||||||
[
|
[
|
||||||
'auth',
|
'auth',
|
||||||
'mail',
|
'mail',
|
||||||
|
'indx',
|
||||||
'pswd',
|
'pswd',
|
||||||
'name',
|
'name',
|
||||||
'simc',
|
'simc',
|
||||||
|
@ -60,6 +61,7 @@ class Account extends Document implements IdentityInterface, PartnerInterface
|
||||||
[
|
[
|
||||||
'auth' => 'Аутентификационный хеш',
|
'auth' => 'Аутентификационный хеш',
|
||||||
'mail' => 'Почта',
|
'mail' => 'Почта',
|
||||||
|
'indx' => 'Псевдоанонимный идентификатор',
|
||||||
'pswd' => 'Пароль',
|
'pswd' => 'Пароль',
|
||||||
'name' => 'Имя',
|
'name' => 'Имя',
|
||||||
'simc' => 'Номер',
|
'simc' => 'Номер',
|
||||||
|
@ -82,9 +84,32 @@ class Account extends Document implements IdentityInterface, PartnerInterface
|
||||||
return array_merge(
|
return array_merge(
|
||||||
parent::rules(),
|
parent::rules(),
|
||||||
[
|
[
|
||||||
[['mail', 'pswd'], 'required', 'message' => 'Заполните поле'],
|
[
|
||||||
['mail', 'email'],
|
[
|
||||||
[['mail', 'comp', 'simc'], 'unique', 'message' => '2']
|
'mail',
|
||||||
|
'pswd'
|
||||||
|
],
|
||||||
|
'required',
|
||||||
|
'message' => 'Заполните поле'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'mail',
|
||||||
|
'email'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'mail',
|
||||||
|
'indx',
|
||||||
|
'comp',
|
||||||
|
'simc'
|
||||||
|
],
|
||||||
|
'unique',
|
||||||
|
'message' => 'Атрибут {attribute} должен иметь уникальное значение'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'indx',
|
||||||
|
'string'
|
||||||
|
]
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -356,7 +381,8 @@ class Account extends Document implements IdentityInterface, PartnerInterface
|
||||||
*
|
*
|
||||||
* @return array Сортированный список
|
* @return array Сортированный список
|
||||||
*/
|
*/
|
||||||
protected function syncListWithSettings(array &$list, string $var): array {
|
protected function syncListWithSettings(array &$list, string $var): array
|
||||||
|
{
|
||||||
// Инициализация текущего значения параметра в начале массива
|
// Инициализация текущего значения параметра в начале массива
|
||||||
if (isset($this->opts[$var])) {
|
if (isset($this->opts[$var])) {
|
||||||
// Параметр найден в настройках аккаунта
|
// Параметр найден в настройках аккаунта
|
||||||
|
@ -387,4 +413,65 @@ class Account extends Document implements IdentityInterface, PartnerInterface
|
||||||
|
|
||||||
return $list;
|
return $list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Генерация псевдоанонимных индексов
|
||||||
|
*
|
||||||
|
* @param [int] $accounts Массив аккаунтов
|
||||||
|
* @param bool $init Параметр обозначающий изменение только для тех у кого ранее идентификатор задан не был (без перезаписи)
|
||||||
|
*
|
||||||
|
* @return int Количество успешно обработанных аккаунтов
|
||||||
|
*/
|
||||||
|
public static function generateIndexes(array $accounts, bool $init = true): int
|
||||||
|
{
|
||||||
|
// Инициализация
|
||||||
|
$amount = 0;
|
||||||
|
|
||||||
|
// Функция для конвертации цифр в буквы
|
||||||
|
$int_to_string = function (int $target): string {
|
||||||
|
$alphabet = ['А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я'];
|
||||||
|
|
||||||
|
return $alphabet[$target];
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach ($accounts as $account) {
|
||||||
|
// Перебор запрошенных аккаунтов
|
||||||
|
|
||||||
|
if (($init && empty($account->indx)) || !$init) {
|
||||||
|
// Запись только тех аккаунтов у кого не инициализирован индекс или если указано отсутствие проверки
|
||||||
|
|
||||||
|
// Повтор генерации
|
||||||
|
regenerate:
|
||||||
|
|
||||||
|
// Генерация
|
||||||
|
$account->indx = $int_to_string(random_int(0, 32)) . $int_to_string(random_int(0, 32)) . $int_to_string(random_int(0, 32));
|
||||||
|
|
||||||
|
// Запись
|
||||||
|
if ($account->save()) {
|
||||||
|
// Аккаунт сохранён (в базе данных это поле проверяется на уникальность)
|
||||||
|
|
||||||
|
if (yii::$app->getRequest()->isConsoleRequest) {
|
||||||
|
// Вызов из терминала
|
||||||
|
|
||||||
|
echo "Удалось сохранить аккаунт с псевдоанонимным идентификатором $account->indx" . PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запись операции в счётчик
|
||||||
|
$amount++;
|
||||||
|
} else {
|
||||||
|
// Аккаунт не сохранен (подразумевается несовпадение идентификаторов)
|
||||||
|
|
||||||
|
if (yii::$app->getRequest()->isConsoleRequest) {
|
||||||
|
// Вызов из терминала
|
||||||
|
|
||||||
|
echo "Не удалось сохранить аккаунт с псевдоанонимным идентификатором $account->indx" . PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto regenerate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $amount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ use app\models\traits\SearchByEdge;
|
||||||
use carono\exchange1c\controllers\ApiController;
|
use carono\exchange1c\controllers\ApiController;
|
||||||
use carono\exchange1c\interfaces\DocumentInterface;
|
use carono\exchange1c\interfaces\DocumentInterface;
|
||||||
|
|
||||||
|
use app\models\connection\Dellin;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,6 +47,7 @@ class Order extends Document implements DocumentInterface
|
||||||
parent::attributes(),
|
parent::attributes(),
|
||||||
[
|
[
|
||||||
'ocid',
|
'ocid',
|
||||||
|
'stts',
|
||||||
'sync'
|
'sync'
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
@ -59,6 +62,7 @@ class Order extends Document implements DocumentInterface
|
||||||
parent::attributeLabels(),
|
parent::attributeLabels(),
|
||||||
[
|
[
|
||||||
'ocid' => 'Идентификатор 1C',
|
'ocid' => 'Идентификатор 1C',
|
||||||
|
'stts' => 'Статус',
|
||||||
'sync' => 'Статус синхронизации с 1C'
|
'sync' => 'Статус синхронизации с 1C'
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
@ -92,7 +96,7 @@ class Order extends Document implements DocumentInterface
|
||||||
public function connect(Account $account): ?AccountEdgeOrder
|
public function connect(Account $account): ?AccountEdgeOrder
|
||||||
{
|
{
|
||||||
// Запись ребра: АККАУНТ -> ЗАКАЗ
|
// Запись ребра: АККАУНТ -> ЗАКАЗ
|
||||||
return AccountEdgeOrder::write($account->id, $this->readId(), 'current') ?? throw new Exception('Не удалось инициализировать ребро: АККАУНТ -> ЗАКАЗ');
|
return AccountEdgeOrder::write($account->readId(), $this->readId(), 'current') ?? throw new Exception('Не удалось инициализировать ребро: АККАУНТ -> ЗАКАЗ');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -110,7 +114,7 @@ class Order extends Document implements DocumentInterface
|
||||||
public function writeSupply(Supply|string|array $supply, Account $trgt = null): int
|
public function writeSupply(Supply|string|array $supply, Account $trgt = null): int
|
||||||
{
|
{
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$trgt ?? $trgt = yii::$app->user ?? throw new Exception('Не удалось инициализировать заказчика');
|
$trgt ?? $trgt = yii::$app->user->identity ?? throw new Exception('Не удалось инициализировать заказчика');
|
||||||
|
|
||||||
if ($supply instanceof Supply) {
|
if ($supply instanceof Supply) {
|
||||||
// Передана инстанция класса поставки или второй элемент массива не является числом
|
// Передана инстанция класса поставки или второй элемент массива не является числом
|
||||||
|
@ -235,7 +239,7 @@ class Order extends Document implements DocumentInterface
|
||||||
public static function search(Account $account = null, string $type = 'current', int $limit = 1, int $page = 1, string $select = null): self|array|null
|
public static function search(Account $account = null, string $type = 'current', int $limit = 1, int $page = 1, string $select = null): self|array|null
|
||||||
{
|
{
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$account or $account = yii::$app->user ?? throw new Exception('Не удалось инициализировать пользователя');
|
$account or $account = yii::$app->user->identity ?? throw new Exception('Не удалось инициализировать пользователя');
|
||||||
|
|
||||||
// Генерация сдвига по запрашиваемым данным (пагинация)
|
// Генерация сдвига по запрашиваемым данным (пагинация)
|
||||||
$offset = $limit * ($page - 1);
|
$offset = $limit * ($page - 1);
|
||||||
|
@ -255,7 +259,7 @@ class Order extends Document implements DocumentInterface
|
||||||
to: 'order',
|
to: 'order',
|
||||||
subquery_where: [
|
subquery_where: [
|
||||||
[
|
[
|
||||||
'account._id' => $account->id
|
'account._id' => $account->readId()
|
||||||
],
|
],
|
||||||
$where_type
|
$where_type
|
||||||
],
|
],
|
||||||
|
@ -281,8 +285,8 @@ class Order extends Document implements DocumentInterface
|
||||||
// Генерация сдвига по запрашиваемым данным (пагинация)
|
// Генерация сдвига по запрашиваемым данным (пагинация)
|
||||||
$offset = $limit * ($page - 1);
|
$offset = $limit * ($page - 1);
|
||||||
|
|
||||||
// Поиск рёбер: ЗАКАЗ -> ПОСТАВКА
|
// Поиск по рёбрам: ЗАКАЗ -> ПОСТАВКА
|
||||||
$supplies = Supply::searchByEdge(
|
$connections = Supply::searchByEdge(
|
||||||
from: 'order',
|
from: 'order',
|
||||||
to: 'supply',
|
to: 'supply',
|
||||||
edge: 'order_edge_supply',
|
edge: 'order_edge_supply',
|
||||||
|
@ -295,21 +299,22 @@ class Order extends Document implements DocumentInterface
|
||||||
where: 'edge._to == supply._id',
|
where: 'edge._to == supply._id',
|
||||||
limit: $limit,
|
limit: $limit,
|
||||||
offset: $offset,
|
offset: $offset,
|
||||||
direction: 'INBOUND'
|
direction: 'INBOUND',
|
||||||
|
select: '{supply, order_edge_supply}'
|
||||||
);
|
);
|
||||||
|
|
||||||
// Инициализация реестра дубликатов
|
// Инициализация реестра дубликатов
|
||||||
$registry = [];
|
$registry = [];
|
||||||
|
|
||||||
// Подсчёт и перестройка массива для очистки от дубликатов
|
// Подсчёт и перестройка массива для очистки от дубликатов
|
||||||
foreach ($supplies as $key => &$supply) {
|
foreach ($connections as $key => &$connection) {
|
||||||
// Перебор поставок
|
// Перебор поставок
|
||||||
|
|
||||||
if (in_array($supply->catn, $registry)) {
|
if (in_array($connection['supply']['catn'], $registry)) {
|
||||||
// Если данная поставка найдена в реестре
|
// Если данная поставка найдена в реестре
|
||||||
|
|
||||||
// Удаление
|
// Удаление
|
||||||
unset($supplies[$key]);
|
unset($connections[$key]);
|
||||||
|
|
||||||
// Пропуск итерации
|
// Пропуск итерации
|
||||||
continue;
|
continue;
|
||||||
|
@ -319,47 +324,56 @@ class Order extends Document implements DocumentInterface
|
||||||
$amount = 0;
|
$amount = 0;
|
||||||
|
|
||||||
// Повторный перебор для поиска дубликатов
|
// Повторный перебор для поиска дубликатов
|
||||||
foreach ($supplies as &$supply4check) {
|
foreach ($connections as &$connection_for_check) {
|
||||||
if ($supply == $supply4check) {
|
if ($connection == $connection_for_check) {
|
||||||
// Найден дубликат
|
// Найден дубликат
|
||||||
|
|
||||||
// Постинкрементация счётчика
|
// Постинкрементация счётчика
|
||||||
$amount++;
|
$amount++;
|
||||||
|
|
||||||
// Запись в реестр
|
// Запись в реестр
|
||||||
$registry[] = $supply4check->catn;
|
$registry[] = $connection_for_check['supply']['catn'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Запись количества для заказа
|
// Запись количества для заказа
|
||||||
$supply->amnt = $amount;
|
$connection['amount'] = $amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Поиск стоимости для каждой поставки
|
// Инициализация дополнительных данных
|
||||||
foreach ($supplies as $key => &$supply) {
|
foreach ($connections as $key => &$connection) {
|
||||||
// Перебор поставок
|
// Перебор поставок
|
||||||
|
|
||||||
// Чтение стоимости
|
// Чтение стоимости
|
||||||
$cost = $supply->readCost();
|
$cost = Supply::readCostById($connection['supply']['_id']);
|
||||||
|
|
||||||
if ($cost < 1) {
|
if (empty($cost) || $cost['ЦенаЗаЕдиницу'] < 1) {
|
||||||
// Если стоимость равна нулю (явная ошибка)
|
// Если стоимость не найдена или равна нулю (явная ошибка)
|
||||||
|
|
||||||
// Удаление из базы данных
|
// Удаление из базы данных
|
||||||
$this->deleteSupply($supply->readId());
|
$this->deleteSupply($connection['supply']->readId());
|
||||||
|
|
||||||
// Удаление из списка
|
// Удаление из списка
|
||||||
unset($supplies[$key]);
|
unset($connections[$key]);
|
||||||
|
|
||||||
// Пропуск итерации
|
// Пропуск итерации
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Запись цены
|
// Поиск ребра до аккаунта
|
||||||
$supply->cost = $cost['ЦенаЗаЕдиницу'] . ' ' . $cost['Валюта'];
|
$connection['account'] = Supply::searchAccountById($connection['supply']['_id']);
|
||||||
|
|
||||||
|
// Инициализация доставки
|
||||||
|
$connection['delivery'] = Dellin::calcDelivery($connection['account']['opts']['delivery_from_city'] ?? $settings['delivery_from_city_default'] ?? '2700000100000000000000000', yii::$app->user->identity->opts['delivery_to_city'] ?? $settings['delivery_to_city_default'] ?? '2700000100000000000000000')['terminals_standard'];
|
||||||
|
|
||||||
|
// Запись цены (цена поставки + цена доставки + наша наценка)
|
||||||
|
$connection['cost'] = ($cost['ЦенаЗаЕдиницу'] ?? $connection['supply']->onec['Цены']['Цена']['ЦенаЗаЕдиницу']) + ($connection['delivery']['price'] ?? 0) + ($settings['increase'] ?? 0);
|
||||||
|
|
||||||
|
// Запись валюты
|
||||||
|
$connection['currency'] = $cost['Валюта'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $supplies;
|
return $connections;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,8 +6,57 @@ namespace app\models;
|
||||||
|
|
||||||
class OrderEdgeSupply extends Edge
|
class OrderEdgeSupply extends Edge
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Имя коллекции
|
||||||
|
*/
|
||||||
public static function collectionName(): string
|
public static function collectionName(): string
|
||||||
{
|
{
|
||||||
return 'order_edge_supply';
|
return 'order_edge_supply';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Свойства
|
||||||
|
*/
|
||||||
|
public function attributes(): array
|
||||||
|
{
|
||||||
|
return array_merge(
|
||||||
|
parent::attributes(),
|
||||||
|
[
|
||||||
|
'comm'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Метки свойств
|
||||||
|
*/
|
||||||
|
public function attributeLabels(): array
|
||||||
|
{
|
||||||
|
return array_merge(
|
||||||
|
parent::attributeLabels(),
|
||||||
|
[
|
||||||
|
'comm' => 'Комментарий к заказу'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Поиск поставки по артикулу
|
||||||
|
*
|
||||||
|
* @param string $catn Артикул
|
||||||
|
* @param int $limit Максимальное количество
|
||||||
|
*
|
||||||
|
* @return array Поставки
|
||||||
|
*/
|
||||||
|
public static function searchBySupplyCatn(string $catn, int $limit = 10): array
|
||||||
|
{
|
||||||
|
if ($supply = Supply::searchByCatn($catn, 1)) {
|
||||||
|
// Поставка найдена
|
||||||
|
|
||||||
|
return self::find()->where(['_to' => $supply->readId()])->limit($limit)->all();
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -565,14 +565,31 @@ class Supply extends Product implements ProductInterface, OfferInterface
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Прочитать стоимость
|
* Прочитать стоимость
|
||||||
|
*
|
||||||
|
* @param Product|null $product Товар для поиска по вершинам
|
||||||
|
*
|
||||||
|
* @return array|null Данные о ценах
|
||||||
*/
|
*/
|
||||||
public function readCost(Product $product = null): array
|
public function readCost(Product $product = null): ?array
|
||||||
|
{
|
||||||
|
return static::readCostById($this->readId(), $product);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Прочитать стоимость по идентификатору поставки
|
||||||
|
*
|
||||||
|
* @param string $_id Идентификатор поставки
|
||||||
|
* @param Product|null $product Товар для поиска по вершинам
|
||||||
|
*
|
||||||
|
* @return array|null Данные о ценах
|
||||||
|
*/
|
||||||
|
public static function readCostById(string $_id, Product $product = null): ?array
|
||||||
{
|
{
|
||||||
if (isset($product)) {
|
if (isset($product)) {
|
||||||
return SupplyEdgeProduct::searchByVertex($this->readId(), $product->readId(), type: 'connect', limit: 1)['onec']['Цены']['Цена'];
|
return SupplyEdgeProduct::searchByVertex($_id, $product->readId(), type: 'connect', limit: 1)['onec']['Цены']['Цена'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return SupplyEdgeProduct::search($this->readId(), type: 'connect', limit: 1)['onec']['Цены']['Цена'];
|
return SupplyEdgeProduct::search($_id, type: 'connect', limit: 1)['onec']['Цены']['Цена'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -582,7 +599,7 @@ class Supply extends Product implements ProductInterface, OfferInterface
|
||||||
*/
|
*/
|
||||||
public function searchAccount(): ?array
|
public function searchAccount(): ?array
|
||||||
{
|
{
|
||||||
return static::searchAccountById($this->_id);
|
return static::searchAccountById($this->readId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -55,6 +55,76 @@ class Dellin extends Model
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Рассчет доставки (расширенный)
|
||||||
|
*
|
||||||
|
* @param string $from Номер КЛАДР
|
||||||
|
* @param string $to Номер КЛАДР
|
||||||
|
* @param int $weight Вес (кг)
|
||||||
|
* @param int $x Ширина (см)
|
||||||
|
* @param int $y Высота (см)
|
||||||
|
* @param int $z Длинна (см)
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function calcDeliveryAdvanced(string $from, string $to, int $weight, int $x, int $y, int $z): array
|
||||||
|
{
|
||||||
|
return self::handle(function () use ($from, $to, $weight, $x, $y, $z) {
|
||||||
|
// Всё готово к работе
|
||||||
|
|
||||||
|
// Рассчёт типа доставки
|
||||||
|
if (
|
||||||
|
$weight <= 10
|
||||||
|
&& (($x <= 5.4 && $y <= 3.9 && $z <= 3.9)
|
||||||
|
|| ($x <= 3.9 && $y <= 5.4 && $z <= 3.9)
|
||||||
|
|| ($x <= 3.9 && $y <= 3.9 && $z <= 5.4))
|
||||||
|
&& $x * $y * $z <= 1000000
|
||||||
|
) {
|
||||||
|
// Доставка категории "small"
|
||||||
|
|
||||||
|
$type = 'small';
|
||||||
|
} else {
|
||||||
|
// Доставка категории "auto"
|
||||||
|
|
||||||
|
$type = 'auto';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запрос
|
||||||
|
$request = self::$browser->post('/v1/micro_calc.json', [
|
||||||
|
'json' => [
|
||||||
|
'appkey' => yii::$app->params['dellin']['key'],
|
||||||
|
'sessionID' => self::$session,
|
||||||
|
'delivery' => [
|
||||||
|
'deliveryType' => [
|
||||||
|
'type' => $type
|
||||||
|
],
|
||||||
|
'arrival' => [
|
||||||
|
'variant' => 'terminal',
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($request->getStatusCode() === 200) {
|
||||||
|
// Запрос прошел успешно
|
||||||
|
|
||||||
|
// Инициализация
|
||||||
|
$response = json_decode((string) $request->getBody(), true);
|
||||||
|
|
||||||
|
if ($response['metadata']['status'] === 200) {
|
||||||
|
// Со стороны ДеловыеЛинии ошибок нет
|
||||||
|
|
||||||
|
return $response['data'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception('На стороне сервера ДеловыеЛинии какие-то проблемы, либо отправлен неверный запрос', 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception('Не удалось запросить рассчёт доставки у ДеловыеЛинии', 500);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Рассчет доставки
|
* Рассчет доставки
|
||||||
*
|
*
|
||||||
|
@ -103,9 +173,9 @@ class Dellin extends Model
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Синхронизация городов
|
* Импорт городов
|
||||||
*
|
*
|
||||||
* @return array|null Найденные города
|
* @return array|null Сохранённые города
|
||||||
*/
|
*/
|
||||||
public static function importCities(): ?int
|
public static function importCities(): ?int
|
||||||
{
|
{
|
||||||
|
@ -137,94 +207,217 @@ class Dellin extends Model
|
||||||
'sink' => $file = $dir . time() . '.csv'
|
'sink' => $file = $dir . time() . '.csv'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Проверка хеша
|
// Проверка хеша (оказалось это хеш запроса, бесполезный)
|
||||||
if ($hash_target !== $hash_received = md5_file($file)) {
|
// if ($hash_target === $hash_received = md5_file($file)) {
|
||||||
// Удалось пройти проверку на хеши файлов
|
// Удалось пройти проверку на хеши файлов
|
||||||
|
|
||||||
// Инициализация (чтение файла)
|
// Инициализация (чтение файла)
|
||||||
$file = fopen($file, "r");
|
$file = fopen($file, "r");
|
||||||
$first_raw_block = true;
|
$first_raw_block = true;
|
||||||
|
|
||||||
while ($row = fgets($file, 4096)) {
|
while ($row = fgets($file, 4096)) {
|
||||||
// Перебор строк
|
// Перебор строк
|
||||||
|
|
||||||
if ($first_raw_block) {
|
if ($first_raw_block) {
|
||||||
// Сработала защита от чтения первой строки файла (указываются названия колонок)
|
// Сработала защита от чтения первой строки файла (указываются названия колонок)
|
||||||
|
|
||||||
// Отключение
|
// Отключение
|
||||||
$first_raw_block = false;
|
$first_raw_block = false;
|
||||||
|
|
||||||
// Пропуск цикла
|
// Пропуск цикла
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
// Инициализация
|
|
||||||
$data = explode(',', $row, 4);
|
|
||||||
$amount = 0;
|
|
||||||
|
|
||||||
// Очистка
|
|
||||||
array_walk($data, fn (&$value) => $value = trim($value, '"'));
|
|
||||||
|
|
||||||
if ($city = City::searchByDellinId($data[0])) {
|
|
||||||
// Удалось найти город в базе данных
|
|
||||||
|
|
||||||
$after_import_log = function () use ($city): void {
|
|
||||||
// Запись в журнал
|
|
||||||
$city->journal('update');
|
|
||||||
|
|
||||||
if (yii::$app->getRequest()->isConsoleRequest) {
|
|
||||||
// Вызов из терминала
|
|
||||||
|
|
||||||
echo 'Удалось перезаписать город: ' . $city->name . PHP_EOL;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// Не удалось найти город в базе данных
|
|
||||||
|
|
||||||
$city = new City();
|
|
||||||
|
|
||||||
$after_import_log = function () use ($city): void {
|
|
||||||
if (yii::$app->getRequest()->isConsoleRequest) {
|
|
||||||
// Вызов из терминала
|
|
||||||
|
|
||||||
echo 'Удалось записать город: ' . $city->name . PHP_EOL;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Запись
|
|
||||||
$city->indx = $data[0];
|
|
||||||
$city->name = $data[1];
|
|
||||||
$city->code = $data[2];
|
|
||||||
$city->term = (bool) $data[3];
|
|
||||||
|
|
||||||
// Отправка в базу данных
|
|
||||||
if ($city->save()) {
|
|
||||||
// Удалось сохранить в базе данных
|
|
||||||
|
|
||||||
// Запись в журнал
|
|
||||||
$after_import_log();
|
|
||||||
|
|
||||||
// Постинкрементация счётчика
|
|
||||||
$amount++;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
// Не удалось сохранить в базе данных
|
|
||||||
|
|
||||||
throw new Exception('Не удалось сохранить город ' . $data[1] . ' в базу данных', 500);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Деинициализация
|
// Инициализация
|
||||||
fclose($file);
|
$data = explode(',', $row, 4);
|
||||||
|
$amount = 0;
|
||||||
|
|
||||||
return $amount;
|
// Очистка
|
||||||
} else {
|
array_walk($data, fn (&$value) => $value = trim($value, '"'));
|
||||||
// Не удалось пройти проверку на соответствие хешей файлов
|
|
||||||
|
|
||||||
throw new Exception('Хеши файлов не совпадают. Должен быть: "' . $hash_target . '", получен: "' . $hash_received . '"', 500);
|
if ($city = City::searchByDellinId($data[0])) {
|
||||||
|
// Удалось найти город в базе данных
|
||||||
|
|
||||||
|
$after_import_log = function () use ($city): void {
|
||||||
|
// Запись в журнал
|
||||||
|
$city->journal('update');
|
||||||
|
|
||||||
|
if (yii::$app->getRequest()->isConsoleRequest) {
|
||||||
|
// Вызов из терминала
|
||||||
|
|
||||||
|
echo 'Удалось перезаписать город: ' . $city->name . PHP_EOL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Не удалось найти город в базе данных
|
||||||
|
|
||||||
|
$city = new City();
|
||||||
|
|
||||||
|
$after_import_log = function () use ($city): void {
|
||||||
|
if (yii::$app->getRequest()->isConsoleRequest) {
|
||||||
|
// Вызов из терминала
|
||||||
|
|
||||||
|
echo 'Удалось записать город: ' . $city->name . PHP_EOL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запись
|
||||||
|
$city->indx = $data[0];
|
||||||
|
$city->name = $data[1];
|
||||||
|
$city->code = $data[2];
|
||||||
|
$city->term = (bool) $data[3];
|
||||||
|
|
||||||
|
// Отправка в базу данных
|
||||||
|
if ($city->save()) {
|
||||||
|
// Удалось сохранить в базе данных
|
||||||
|
|
||||||
|
// Запись в журнал
|
||||||
|
$after_import_log();
|
||||||
|
|
||||||
|
// Постинкрементация счётчика
|
||||||
|
$amount++;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// Не удалось сохранить в базе данных
|
||||||
|
|
||||||
|
throw new Exception('Не удалось сохранить город ' . $data[1] . ' в базу данных', 500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Деинициализация
|
||||||
|
fclose($file);
|
||||||
|
|
||||||
|
return $amount;
|
||||||
|
// } else {
|
||||||
|
// // Не удалось пройти проверку на соответствие хешей файлов
|
||||||
|
|
||||||
|
// throw new Exception('Хеши файлов не совпадают. Должен быть: "' . $hash_target . '", получен: "' . $hash_received . '"', 500);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception('Не удалось синхронизировать данные городов с ДеловыеЛинии', 500);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Импорт терминалов
|
||||||
|
*
|
||||||
|
* @return array|null Сохранённые терминалы
|
||||||
|
*/
|
||||||
|
public static function importTerminals(): ?int
|
||||||
|
{
|
||||||
|
return self::handle(function () {
|
||||||
|
// Всё готово к работе
|
||||||
|
|
||||||
|
// Запрос ссылки на файл с городами, возвращает ['hash' => string, 'url' => string]
|
||||||
|
$request = self::$browser->post('/v3/public/terminals.json', [
|
||||||
|
'json' => [
|
||||||
|
'appkey' => yii::$app->params['dellin']['key'],
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($request->getStatusCode() === 200) {
|
||||||
|
// Запрос прошел успешно
|
||||||
|
|
||||||
|
// Инициализация
|
||||||
|
$response = json_decode((string) $request->getBody(), true);
|
||||||
|
$dir = YII_PATH_PUBLIC . '/../assets/import/' . date('Y-m-d', time()) . '/dellin/terminals/' . (yii::$app->user->identity->_key ?? 'system') . '/';
|
||||||
|
|
||||||
|
if (!file_exists($dir)) {
|
||||||
|
// Директории не существует
|
||||||
|
|
||||||
|
mkdir($dir, 0775, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = self::$browser->get($response['url'], [
|
||||||
|
'sink' => $file = $dir . time() . '.json'
|
||||||
|
]);
|
||||||
|
|
||||||
|
die;
|
||||||
|
|
||||||
|
|
||||||
|
// Инициализация (чтение файла)
|
||||||
|
$file = fopen($file, "r");
|
||||||
|
$first_raw_block = true;
|
||||||
|
|
||||||
|
while ($row = fgets($file, 4096)) {
|
||||||
|
// Перебор строк
|
||||||
|
|
||||||
|
if ($first_raw_block) {
|
||||||
|
// Сработала защита от чтения первой строки файла (указываются названия колонок)
|
||||||
|
|
||||||
|
// Отключение
|
||||||
|
$first_raw_block = false;
|
||||||
|
|
||||||
|
// Пропуск цикла
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализация
|
||||||
|
$data = explode(',', $row, 4);
|
||||||
|
$amount = 0;
|
||||||
|
|
||||||
|
// Очистка
|
||||||
|
array_walk($data, fn (&$value) => $value = trim($value, '"'));
|
||||||
|
|
||||||
|
if ($city = Terminal::searchByDellinId($data[0])) {
|
||||||
|
// Удалось найти город в базе данных
|
||||||
|
|
||||||
|
$after_import_log = function () use ($city): void {
|
||||||
|
// Запись в журнал
|
||||||
|
$city->journal('update');
|
||||||
|
|
||||||
|
if (yii::$app->getRequest()->isConsoleRequest) {
|
||||||
|
// Вызов из терминала
|
||||||
|
|
||||||
|
echo 'Удалось перезаписать город: ' . $city->name . PHP_EOL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Не удалось найти город в базе данных
|
||||||
|
|
||||||
|
$terminal = new Terminal();
|
||||||
|
|
||||||
|
$after_import_log = function () use ($terminal): void {
|
||||||
|
if (yii::$app->getRequest()->isConsoleRequest) {
|
||||||
|
// Вызов из терминала
|
||||||
|
|
||||||
|
echo 'Удалось записать город: ' . $terminal->name . PHP_EOL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запись
|
||||||
|
$terminal->indx = $data[0];
|
||||||
|
$terminal->name = $data[1];
|
||||||
|
$terminal->code = $data[2];
|
||||||
|
$terminal->term = (bool) $data[3];
|
||||||
|
|
||||||
|
// Отправка в базу данных
|
||||||
|
if ($terminal->save()) {
|
||||||
|
// Удалось сохранить в базе данных
|
||||||
|
|
||||||
|
// Запись в журнал
|
||||||
|
$after_import_log();
|
||||||
|
|
||||||
|
// Постинкрементация счётчика
|
||||||
|
$amount++;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// Не удалось сохранить в базе данных
|
||||||
|
|
||||||
|
throw new Exception('Не удалось сохранить город ' . $data[1] . ' в базу данных', 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Деинициализация
|
||||||
|
fclose($file);
|
||||||
|
|
||||||
|
return $amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception('Не удалось синхронизировать данные городов с ДеловыеЛинии', 500);
|
throw new Exception('Не удалось синхронизировать данные городов с ДеловыеЛинии', 500);
|
||||||
|
|
|
@ -69,6 +69,7 @@ trait SearchByEdge
|
||||||
$request = $query
|
$request = $query
|
||||||
->foreach($foreach)
|
->foreach($foreach)
|
||||||
->where($where)
|
->where($where)
|
||||||
|
->limit($limit)
|
||||||
->select($select ?? $to);
|
->select($select ?? $to);
|
||||||
|
|
||||||
// Режим проверки
|
// Режим проверки
|
||||||
|
@ -84,6 +85,8 @@ trait SearchByEdge
|
||||||
|
|
||||||
return $handle($request);
|
return $handle($request);
|
||||||
} else if (isset($select)) {
|
} else if (isset($select)) {
|
||||||
|
// Указан выбор свойств
|
||||||
|
|
||||||
$response = $request->createCommand()->execute()->getAll();
|
$response = $request->createCommand()->execute()->getAll();
|
||||||
|
|
||||||
if ($asArray) {
|
if ($asArray) {
|
||||||
|
@ -103,9 +106,7 @@ trait SearchByEdge
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
} else {
|
} else {
|
||||||
if ($limit === 1) {
|
// Иначе просто запросить для ActiveQuery
|
||||||
return $request->one();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $request->all();
|
return $request->all();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use yii;
|
||||||
|
|
||||||
|
use app\models\connection\Dellin;
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
<link href="/css/pages/cart.css" rel="stylesheet">
|
<link href="/css/pages/cart.css" rel="stylesheet">
|
||||||
|
|
||||||
<div id="page_cart" class="container mb-auto py-3">
|
<div id="page_cart" class="container mb-auto py-3">
|
||||||
|
@ -6,7 +14,7 @@
|
||||||
<div class="col mb-4 list rounded overflow-hidden">
|
<div class="col mb-4 list rounded overflow-hidden">
|
||||||
<div class="row py-2">
|
<div class="row py-2">
|
||||||
<div class="pl-3 mr-1">
|
<div class="pl-3 mr-1">
|
||||||
<input id="checkbox_cart_all" type="checkbox" onchange="return cart_list_checkbox(this);"/>
|
<input id="checkbox_cart_all" type="checkbox" onchange="return cart_list_checkbox(this);" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
<span>Артикул</span>
|
<span>Артикул</span>
|
||||||
|
@ -25,27 +33,48 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php
|
<?php
|
||||||
if (isset($supplies) && !empty($supplies)) {
|
if (isset($connections) && !empty($connections)) {
|
||||||
foreach ($supplies as $supply) {
|
foreach ($connections as $connection) {
|
||||||
|
// Перебор поставок
|
||||||
|
|
||||||
|
// Инициализация доставки
|
||||||
|
$delivery = $connection['delivery']['period_to'];
|
||||||
|
|
||||||
|
// Инициализация цены
|
||||||
|
$cost = $connection['cost'] . ' ' . $connection['currency'];
|
||||||
|
|
||||||
|
// Инициализация комментария
|
||||||
|
$comment = $connection['order_edge_supply'][0]['comm'] ?? 'Комментарий к заказу';
|
||||||
|
|
||||||
echo <<<HTML
|
echo <<<HTML
|
||||||
<div class="row py-2 cart_list_target">
|
<div class="row py-2 cart_list_target">
|
||||||
<div class="pl-3 mr-1">
|
<div class="col">
|
||||||
<input id="cart_list_checkbox_$supply->catn" type="checkbox" onchange="return cart_list_checkbox(this);"/>
|
<div class="row">
|
||||||
</div>
|
<div class="pl-3 my-auto mr-1">
|
||||||
<div class="col-2">
|
<input id="cart_list_checkbox_{$connection['supply']['catn']}" type="checkbox" onchange="return cart_list_checkbox(this);"/>
|
||||||
$supply->catn
|
</div>
|
||||||
</div>
|
<div class="col-2 my-auto">
|
||||||
<div class="col-4">
|
{$connection['supply']['catn']}
|
||||||
$supply->dscr
|
</div>
|
||||||
</div>
|
<div class="col-4 my-auto">
|
||||||
<div class="col-1 ml-auto">
|
{$connection['supply']['dscr']}
|
||||||
<input id="cart_list_amnt_$supply->catn" class="form-control text-center" type="text" value="$supply->amnt" onchange="return cart_list_amount_update('$supply->catn', this)" aria-invalid="false">
|
</div>
|
||||||
</div>
|
<div class="col-1 my-auto ml-auto">
|
||||||
<div class="col-2 text-right">
|
<input id="cart_list_amnt_{$connection['supply']['catn']}" class="form-control text-center" type="text" value="{$connection['amount']}" onchange="return cart_list_amount_update('{$connection['supply']['catn']}', this)" aria-invalid="false">
|
||||||
$supply->time
|
</div>
|
||||||
</div>
|
<div class="col-2 my-auto text-right">
|
||||||
<div class="col-2 mr-3 text-right">
|
$delivery дней
|
||||||
$supply->cost
|
</div>
|
||||||
|
<div class="col-2 my-auto mr-3 text-right">
|
||||||
|
$cost
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
<div class="row mb-1">
|
||||||
|
<div class="col-12">
|
||||||
|
<p id="cart_list_comment_{$connection['supply']['catn']}" class="mt-0 ml-0 text-break pointer-event" role="button" onclick="return cart_list_comment_edit('{$connection['supply']['catn']}', this);">$comment</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
HTML;
|
HTML;
|
||||||
|
|
|
@ -1,11 +1,3 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use yii;
|
|
||||||
|
|
||||||
use app\models\connection\Dellin;
|
|
||||||
|
|
||||||
?>
|
|
||||||
|
|
||||||
<link href="/css/pages/search.css" rel="stylesheet">
|
<link href="/css/pages/search.css" rel="stylesheet">
|
||||||
|
|
||||||
<div id="page_search" class="container flex-grow-1 d-flex">
|
<div id="page_search" class="container flex-grow-1 d-flex">
|
||||||
|
@ -75,7 +67,7 @@ use app\models\connection\Dellin;
|
||||||
$catn = $supply['catn'] ?? $supply['onec']['Артикул'];
|
$catn = $supply['catn'] ?? $supply['onec']['Артикул'];
|
||||||
|
|
||||||
// Инициализация цены
|
// Инициализация цены
|
||||||
$price_raw = $supply['prce'] ?? $supply['onec']['Цены']['Цена']['ЦенаЗаЕдиницу'];
|
$price_raw = $supply['prce'];
|
||||||
$price = $price_raw . ' ' . $supply['onec']['Цены']['Цена']['Валюта'];
|
$price = $price_raw . ' ' . $supply['onec']['Цены']['Цена']['Валюта'];
|
||||||
|
|
||||||
// Инициализация количества
|
// Инициализация количества
|
||||||
|
@ -88,9 +80,10 @@ use app\models\connection\Dellin;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Инициализация доставки
|
// Инициализация доставки
|
||||||
$delivery = Dellin::calcDelivery($supply['account']['opts']['delivery_from_city'], yii::$app->user->identity->opts['delivery_to_city'])['terminals_standard'];
|
$delivery = $supply['delivery']['max'];
|
||||||
$delivery_max = $delivery['period_to'] ?? 'Неизвестно';
|
|
||||||
$delivery_price = $delivery['price'] ?? 'Неизвестно';
|
// Инициализация индекса аккаунта
|
||||||
|
$index = $supply['account']['indx'] ?? 'Неизвестен';
|
||||||
|
|
||||||
if ($amount_raw < 1 || $price_raw < 1) {
|
if ($amount_raw < 1 || $price_raw < 1) {
|
||||||
// Нет в наличии или цена 0 рублей
|
// Нет в наличии или цена 0 рублей
|
||||||
|
@ -109,17 +102,19 @@ use app\models\connection\Dellin;
|
||||||
|
|
||||||
$supplies_html .= <<<HTML
|
$supplies_html .= <<<HTML
|
||||||
<div class="row my-auto m-0 h-100 text-right">
|
<div class="row my-auto m-0 h-100 text-right">
|
||||||
<small class="col-2 my-auto ml-auto">
|
<small class="col-1 my-auto ml-auto pl-2 pr-0">
|
||||||
|
$index
|
||||||
|
</small>
|
||||||
|
<small class="col-1 my-auto pl-2 pr-0">
|
||||||
$amount
|
$amount
|
||||||
</small>
|
</small>
|
||||||
<small class="col-2 my-auto ml-1">
|
<small class="col-1 my-auto pl-2 pr-0 mr-2">
|
||||||
$delivery_max дней<br/>
|
$delivery дн
|
||||||
$delivery_price рублей
|
|
||||||
</small>
|
</small>
|
||||||
<b class="col-2 my-auto">
|
<b class="col-2 my-auto">
|
||||||
$price
|
$price
|
||||||
</b>
|
</b>
|
||||||
<a class="col-1 h-100 text-dark d-flex button_white rounded" title="Добавить $catn в корзину" href="/cart" role="button" onclick="return cart_write('$catn');">
|
<a class="col-1 h-100 text-dark d-flex button_white rounded" title="Добавить $catn в корзину" role="button" onclick="return cart_write('$catn');">
|
||||||
<i class="fas fa-cart-arrow-down pr-1 m-auto"></i>
|
<i class="fas fa-cart-arrow-down pr-1 m-auto"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,11 +2,12 @@
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
#page_cart article .list .row:nth-child(2n+1) {
|
#page_cart article .list > .row:nth-child(2n+1) {
|
||||||
background-color: #f7f6f9;
|
background-color: #f7f6f9;
|
||||||
}
|
}
|
||||||
|
|
||||||
#page_cart article .list .row:first-child {
|
#page_cart article .list > .row:first-child {
|
||||||
|
/* border-bottom: 2px solid #bcc2d5; */
|
||||||
background-color: #dbdde3;
|
background-color: #dbdde3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -188,6 +188,61 @@ function cart_cost_calculate() {
|
||||||
document.getElementById('cart_cost').innerHTML = costs;
|
document.getElementById('cart_cost').innerHTML = costs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Изменить количество товара в корзине
|
||||||
|
*/
|
||||||
|
function cart_list_comment_edit(catn, element) {
|
||||||
|
if (catn !== null && catn !== undefined && element !== null && element !== undefined) {
|
||||||
|
element.innerHTML = '<textarea class="form-control" cols="50" rows="5" onchange = "return cart_list_comment_save(\'' + catn + '\', this.parentElement)">' + element.innerText + '</textarea>';
|
||||||
|
|
||||||
|
element.removeAttribute('onclick');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cart_list_comment_save(catn, element) {
|
||||||
|
if (catn !== null && catn !== undefined && element !== null && element !== undefined) {
|
||||||
|
// Инициализация
|
||||||
|
let text = element.children[0].value;
|
||||||
|
|
||||||
|
// Обновление заголовка (предзагрузка)
|
||||||
|
element.innerHTML = text;
|
||||||
|
|
||||||
|
// Запись аттрибута (предзагрузка)
|
||||||
|
element.setAttribute('onclick', 'return cart_list_comment_edit(\'' + catn + '\', this);');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/cart/' + catn + '/edit/comm',
|
||||||
|
type: 'post',
|
||||||
|
dataType: 'json',
|
||||||
|
data: {
|
||||||
|
'_csrf': yii.getCsrfToken(),
|
||||||
|
'text': text
|
||||||
|
},
|
||||||
|
success: function (data, status) {
|
||||||
|
// Заголовок
|
||||||
|
if (data.comm !== undefined && element !== null && element !== undefined) {
|
||||||
|
// Обновление заголовка
|
||||||
|
element.innerHTML = data.comm;
|
||||||
|
|
||||||
|
// Запись аттрибута
|
||||||
|
element.setAttribute('onclick', 'return cart_list_comment_edit(\'' + catn + '\', this);');
|
||||||
|
};
|
||||||
|
|
||||||
|
cart_response_success(data, status);
|
||||||
|
},
|
||||||
|
error: cart_response_error
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
cart_cost_calculate();
|
cart_cost_calculate();
|
||||||
|
|
||||||
function cart_response(data, status) {
|
function cart_response(data, status) {
|
||||||
|
|
Reference in New Issue