Подключение к ДеловыеЛинии
This commit is contained in:
parent
d4bc3e2263
commit
7865cac5d4
|
@ -32,7 +32,7 @@
|
||||||
"version": "3.3.11",
|
"version": "3.3.11",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/RobinHerbots/Inputmask.git",
|
"url": "git@github.com:RobinHerbots/Inputmask.git",
|
||||||
"reference": "5e670ad62f50c738388d4dcec78d2888505ad77b"
|
"reference": "5e670ad62f50c738388d4dcec78d2888505ad77b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
|
@ -1016,7 +1016,7 @@
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.hood.su/mirzaev/yii2/arangodb",
|
"url": "https://git.hood.su/mirzaev/yii2/arangodb",
|
||||||
"reference": "bb7b1b8f8e26c409f9c113a6bd459e3274e94599"
|
"reference": "cbc26916ea54bb767306e4c2750e710b08eecc21"
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.0.0",
|
"php": "^8.0.0",
|
||||||
|
@ -1058,7 +1058,7 @@
|
||||||
"ArangoDb",
|
"ArangoDb",
|
||||||
"yii2"
|
"yii2"
|
||||||
],
|
],
|
||||||
"time": "2021-04-10T16:39:51+00:00"
|
"time": "2021-04-11T19:27:43+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mirzaev/yii2-arangodb-sessions",
|
"name": "mirzaev/yii2-arangodb-sessions",
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\commands;
|
||||||
|
|
||||||
|
use yii\console\Controller;
|
||||||
|
use yii\console\ExitCode;
|
||||||
|
|
||||||
|
use app\models\connection\Dellin;
|
||||||
|
|
||||||
|
class DellinController extends Controller
|
||||||
|
{
|
||||||
|
public function actionCitiesImport()
|
||||||
|
{
|
||||||
|
if (Dellin::importCities()) {
|
||||||
|
return ExitCode::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExitCode::UNSPECIFIED_ERROR;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 {
|
$search = function (bool $new = false, bool $count = false) use ($model, $account, $type, $let, $limit): array|int|null {
|
||||||
if ($count) {
|
if ($count) {
|
||||||
// Запрошен подсчёт непрочитанных уведомлений
|
// Запрошен подсчёт непрочитанных уведомлений
|
||||||
|
|
||||||
|
|
|
@ -245,6 +245,57 @@ class ProductController extends Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function actionEditWght(string $catn): array|string|null
|
||||||
|
{
|
||||||
|
// Инициализация
|
||||||
|
$return = [
|
||||||
|
'_csrf' => yii::$app->request->getCsrfToken()
|
||||||
|
];
|
||||||
|
|
||||||
|
if (is_null($catn)) {
|
||||||
|
// Не получен артикул
|
||||||
|
|
||||||
|
yii::$app->response->statusCode = 500;
|
||||||
|
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($product = Product::searchByCatn($catn)) {
|
||||||
|
// Товар найден
|
||||||
|
|
||||||
|
// Инициализация
|
||||||
|
$text = yii::$app->request->post('text') ?? yii::$app->request->get('text') ?? '0';
|
||||||
|
$text or $text = '0';
|
||||||
|
|
||||||
|
$product->wght = $text;
|
||||||
|
|
||||||
|
if ($product->save()) {
|
||||||
|
// Товар обновлён
|
||||||
|
|
||||||
|
$return['wght'] = $text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Конец алгоритма
|
||||||
|
*/
|
||||||
|
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('/');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function actionWriteImage(string $catn): array|string|null
|
public function actionWriteImage(string $catn): array|string|null
|
||||||
{
|
{
|
||||||
// Инициализация
|
// Инициализация
|
||||||
|
|
|
@ -91,10 +91,6 @@ class ProfileController extends Controller
|
||||||
*/
|
*/
|
||||||
public function actionIndex(): string|array
|
public function actionIndex(): string|array
|
||||||
{
|
{
|
||||||
$browser = new Dellin();
|
|
||||||
|
|
||||||
$browser->syncCities();
|
|
||||||
|
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$model = yii::$app->user->identity;
|
$model = yii::$app->user->identity;
|
||||||
$panel = yii::$app->request->post('panel') ?? yii::$app->request->get('panel');
|
$panel = yii::$app->request->post('panel') ?? yii::$app->request->get('panel');
|
||||||
|
@ -122,8 +118,14 @@ class ProfileController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$account_sections_city_list = null;
|
$delivery_from_city_list = $model->genListCitiesFrom();
|
||||||
$import_sections_oem_list = $model->genListOem(Supply::searchByAccount(select: 'supply.onec["ЗначенияСвойств"]'));
|
$delivery_to_city_list = $model->genListCitiesTo();
|
||||||
|
$import_oem_list = $model->genListOem(Supply::searchByAccount(select: 'supply.onec["ЗначенияСвойств"]'));
|
||||||
|
|
||||||
|
// Сортировка по алфавиту
|
||||||
|
asort($delivery_from_city_list);
|
||||||
|
asort($delivery_to_city_list);
|
||||||
|
asort($import_oem_list);
|
||||||
|
|
||||||
if (yii::$app->request->isPost) {
|
if (yii::$app->request->isPost) {
|
||||||
// POST-запрос
|
// POST-запрос
|
||||||
|
@ -134,8 +136,9 @@ class ProfileController extends Controller
|
||||||
'main' => $this->renderPartial('index', compact(
|
'main' => $this->renderPartial('index', compact(
|
||||||
'model',
|
'model',
|
||||||
'sidebar',
|
'sidebar',
|
||||||
'account_sections_city_list',
|
'delivery_from_city_list',
|
||||||
'import_sections_oem_list',
|
'delivery_to_city_list',
|
||||||
|
'import_oem_list',
|
||||||
'panel'
|
'panel'
|
||||||
)),
|
)),
|
||||||
'redirect' => '/profile',
|
'redirect' => '/profile',
|
||||||
|
@ -146,8 +149,9 @@ class ProfileController extends Controller
|
||||||
return $this->render('index', compact(
|
return $this->render('index', compact(
|
||||||
'model',
|
'model',
|
||||||
'sidebar',
|
'sidebar',
|
||||||
'account_sections_city_list',
|
'delivery_from_city_list',
|
||||||
'import_sections_oem_list',
|
'delivery_to_city_list',
|
||||||
|
'import_oem_list',
|
||||||
'panel'
|
'panel'
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -363,7 +367,6 @@ class ProfileController extends Controller
|
||||||
*/
|
*/
|
||||||
public function actionImport()
|
public function actionImport()
|
||||||
{
|
{
|
||||||
var_dump($_FILES);
|
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$model = new Supply(yii::$app->request->post('Supply') ?? yii::$app->request->get('Supply'));
|
$model = new Supply(yii::$app->request->post('Supply') ?? yii::$app->request->get('Supply'));
|
||||||
$model->scenario = $model::SCENARIO_IMPORT_EXCEL;
|
$model->scenario = $model::SCENARIO_IMPORT_EXCEL;
|
||||||
|
|
|
@ -166,6 +166,11 @@ class SearchController extends Controller
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$row['overload'] = true;
|
$row['overload'] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Поиск аккаунтов владельцев поставок
|
||||||
|
foreach ($row['supplies'] as &$edge) {
|
||||||
|
$edge['account'] = Supply::searchAccountById($edge['_from']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Запись ответа
|
// Запись ответа
|
||||||
|
|
|
@ -273,44 +273,113 @@ class Account extends Document implements IdentityInterface, PartnerInterface
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$list = [];
|
$list = [];
|
||||||
|
|
||||||
// Перебор свойств поставок
|
|
||||||
foreach ($supplies as $supply) {
|
foreach ($supplies as $supply) {
|
||||||
// Инициализация
|
// Перебор поставок
|
||||||
|
if (in_array($supply['ЗначенияСвойства']['Ид'], $list, true)) {
|
||||||
$id = $supply['ЗначенияСвойства']['Ид'];
|
|
||||||
|
|
||||||
if (in_array($id, $list, true)) {
|
|
||||||
// Если встретился дубликат (исполняется очень часто)
|
// Если встретился дубликат (исполняется очень часто)
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Генерация
|
// Генерация
|
||||||
!isset($supply['ЗначенияСвойства']['Наименование']) or $list[$id] = $supply['ЗначенияСвойства']['Наименование'];
|
empty($supply['ЗначенияСвойства']['Наименование']) or $list[$supply['ЗначенияСвойства']['Ид']] = $supply['ЗначенияСвойства']['Наименование'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Инициализация текущего значения параметра в начале массива
|
return $this->syncListWithSettings($list, 'import_supplies_oem');
|
||||||
if (isset($this->opts['import_sections_oem'])) {
|
}
|
||||||
// Параметр 'import_sections_oem' найден в настройках аккаунта
|
|
||||||
|
|
||||||
if (isset($list[$this->opts['import_sections_oem']])) {
|
/**
|
||||||
|
* Генерация списка городов из ДеловыеЛинии для отправителя
|
||||||
|
*
|
||||||
|
* Актуальное (выбранное, активное) значение записывается первым
|
||||||
|
*
|
||||||
|
* @param array Необработанный список городов
|
||||||
|
*/
|
||||||
|
public function genListCitiesFrom(): array
|
||||||
|
{
|
||||||
|
// Инициализация
|
||||||
|
$list = [];
|
||||||
|
|
||||||
|
$cities = City::readAll();
|
||||||
|
|
||||||
|
foreach ($cities as $city) {
|
||||||
|
// Перебор городов
|
||||||
|
|
||||||
|
if (in_array($city->name, $list, true)) {
|
||||||
|
// Если встретился дубликат (исполняется очень часто)
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запись
|
||||||
|
empty($city->name) or $list[$city->code] = $city->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->syncListWithSettings($list, 'delivery_from_city');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Генерация списка городов из ДеловыеЛинии для получателя
|
||||||
|
*
|
||||||
|
* Актуальное (выбранное, активное) значение записывается первым
|
||||||
|
*
|
||||||
|
* @param array Необработанный список городов
|
||||||
|
*/
|
||||||
|
public function genListCitiesTo(): array
|
||||||
|
{
|
||||||
|
// Инициализация
|
||||||
|
$list = [];
|
||||||
|
|
||||||
|
$cities = City::readAll();
|
||||||
|
|
||||||
|
foreach ($cities as $city) {
|
||||||
|
// Перебор городов
|
||||||
|
|
||||||
|
if (in_array($city->name, $list, true)) {
|
||||||
|
// Если встретился дубликат (исполняется очень часто)
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запись
|
||||||
|
empty($city->name) or $list[$city->code] = $city->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->syncListWithSettings($list, 'delivery_to_city');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Синхронизация списка вариантов параметра с текущим значением из настроек
|
||||||
|
*
|
||||||
|
* @param array &$list Список
|
||||||
|
* @param string $var Название параметра
|
||||||
|
*
|
||||||
|
* @return array Сортированный список
|
||||||
|
*/
|
||||||
|
protected function syncListWithSettings(array &$list, string $var): array {
|
||||||
|
// Инициализация текущего значения параметра в начале массива
|
||||||
|
if (isset($this->opts[$var])) {
|
||||||
|
// Параметр найден в настройках аккаунта
|
||||||
|
|
||||||
|
if (isset($list[$this->opts[$var]])) {
|
||||||
// Найдено совпадение сохранённого параметра с полученным списком из поставок
|
// Найдено совпадение сохранённого параметра с полученным списком из поставок
|
||||||
|
|
||||||
// Буфер для сохранения параметра
|
// Буфер для сохранения параметра
|
||||||
$buffer = $list[$this->opts['import_sections_oem']];
|
$buffer = $list[$this->opts[$var]];
|
||||||
|
|
||||||
// Удаление параметра
|
// Удаление параметра
|
||||||
unset($list[$this->opts['import_sections_oem']]);
|
unset($list[$this->opts[$var]]);
|
||||||
|
|
||||||
// Сохранение параметра в начале массива
|
// Сохранение параметра в начале массива
|
||||||
$list = array_merge([$this->opts['import_sections_oem'] => $buffer], $list);
|
$list = array_merge([$this->opts[$var] => $buffer], $list);
|
||||||
} else {
|
} else {
|
||||||
// Совпадение не найдено
|
// Совпадение не найдено
|
||||||
|
|
||||||
// Сохранение параметра из данных аккаунта в начале массива
|
// Сохранение параметра из данных аккаунта в начале массива
|
||||||
$list = array_merge([$this->opts['import_sections_oem'] => $this->opts['import_sections_oem']], $list);
|
$list = array_merge([$this->opts[$var] => $this->opts[$var]], $list);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Параметр 'import_sections_oem' не найден в настройках аккаунта
|
// Параметр $var не найден в настройках аккаунта
|
||||||
|
|
||||||
// Сохранение параметра из данных аккаунта в начале массива
|
// Сохранение параметра из данных аккаунта в начале массива
|
||||||
$list = array_merge(['Выберите'], $list);
|
$list = array_merge(['Выберите'], $list);
|
||||||
|
|
|
@ -16,6 +16,7 @@ class City extends Document
|
||||||
return array_merge(
|
return array_merge(
|
||||||
parent::attributes(),
|
parent::attributes(),
|
||||||
[
|
[
|
||||||
|
'indx',
|
||||||
'name',
|
'name',
|
||||||
'code',
|
'code',
|
||||||
'term'
|
'term'
|
||||||
|
@ -28,10 +29,16 @@ class City extends Document
|
||||||
return array_merge(
|
return array_merge(
|
||||||
parent::rules(),
|
parent::rules(),
|
||||||
[
|
[
|
||||||
|
[
|
||||||
|
'indx',
|
||||||
|
'string'
|
||||||
|
],
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
|
'indx',
|
||||||
'name',
|
'name',
|
||||||
'code'
|
'code',
|
||||||
|
'term'
|
||||||
],
|
],
|
||||||
'required',
|
'required',
|
||||||
'message' => 'Заполните поле: {attribute}'
|
'message' => 'Заполните поле: {attribute}'
|
||||||
|
@ -56,10 +63,19 @@ class City extends Document
|
||||||
return array_merge(
|
return array_merge(
|
||||||
parent::attributeLabels(),
|
parent::attributeLabels(),
|
||||||
[
|
[
|
||||||
|
'indx' => 'Идентификатор в ДеловыеЛинии',
|
||||||
'name' => 'Название',
|
'name' => 'Название',
|
||||||
'code' => 'Код КЛАДР',
|
'code' => 'Код КЛАДР',
|
||||||
'term' => 'Указатель наличия терминала в городе'
|
'term' => 'Указатель наличия терминала в городе'
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Поиск по идентификатору в ДеловыеЛинии
|
||||||
|
*/
|
||||||
|
public static function searchByDellinId(string $indx): ?static
|
||||||
|
{
|
||||||
|
return static::findOne(['indx' => $indx]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ abstract class Document extends ActiveRecord
|
||||||
$this->jrnl = array_merge(
|
$this->jrnl = array_merge(
|
||||||
[[
|
[[
|
||||||
'date' => time(),
|
'date' => time(),
|
||||||
'account' => yii::$app->user->id,
|
'account' => yii::$app->user->id ?? 'system',
|
||||||
'action' => 'create'
|
'action' => 'create'
|
||||||
]],
|
]],
|
||||||
$this->jrnl ?? []
|
$this->jrnl ?? []
|
||||||
|
@ -106,7 +106,7 @@ abstract class Document extends ActiveRecord
|
||||||
[array_merge(
|
[array_merge(
|
||||||
[
|
[
|
||||||
'date' => $time = time(),
|
'date' => $time = time(),
|
||||||
'account' => yii::$app->user->id,
|
'account' => yii::$app->user->id ?? 'system',
|
||||||
'action' => $action
|
'action' => $action
|
||||||
],
|
],
|
||||||
...$data
|
...$data
|
||||||
|
|
|
@ -80,6 +80,7 @@ class Product extends Document
|
||||||
'dscr',
|
'dscr',
|
||||||
'prod',
|
'prod',
|
||||||
'dmns',
|
'dmns',
|
||||||
|
'wght',
|
||||||
'imgs',
|
'imgs',
|
||||||
'time'
|
'time'
|
||||||
]
|
]
|
||||||
|
@ -99,6 +100,7 @@ class Product extends Document
|
||||||
'dscr' => 'Описание (dscr)',
|
'dscr' => 'Описание (dscr)',
|
||||||
'prod' => 'Производитель (prod)',
|
'prod' => 'Производитель (prod)',
|
||||||
'dmns' => 'Габариты (dmns)',
|
'dmns' => 'Габариты (dmns)',
|
||||||
|
'wght' => 'Вес (wght)',
|
||||||
'imgs' => 'Изображения (imgs)',
|
'imgs' => 'Изображения (imgs)',
|
||||||
'time' => 'Срок доставки (time)',
|
'time' => 'Срок доставки (time)',
|
||||||
'file_excel' => 'Документ (file_excel)',
|
'file_excel' => 'Документ (file_excel)',
|
||||||
|
@ -301,7 +303,7 @@ class Product extends Document
|
||||||
// Перебор файлов
|
// Перебор файлов
|
||||||
|
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$dir = '../assets/import/' . date('Y_m_d#H-i', time()) . '/excel/';
|
$dir = YII_PATH_PUBLIC . '../assets/import/' . date('Y-m-d', time()) . '/excel/' . (yii::$app->user->identity->_key ?? 'system') . '/' . time() . '/';
|
||||||
|
|
||||||
// Сохранение на диск
|
// Сохранение на диск
|
||||||
if (!file_exists($dir)) {
|
if (!file_exists($dir)) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ use carono\exchange1c\interfaces\OfferInterface;
|
||||||
use carono\exchange1c\interfaces\ProductInterface;
|
use carono\exchange1c\interfaces\ProductInterface;
|
||||||
use carono\exchange1c\controllers\ApiController;
|
use carono\exchange1c\controllers\ApiController;
|
||||||
|
|
||||||
use exception;
|
use Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Поставка (выгрузка товаров от поставщиков)
|
* Поставка (выгрузка товаров от поставщиков)
|
||||||
|
@ -416,7 +416,8 @@ class Supply extends Product implements ProductInterface, OfferInterface
|
||||||
* @param mixed|null $context
|
* @param mixed|null $context
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getExportFields1c($context = null) {
|
public function getExportFields1c($context = null)
|
||||||
|
{
|
||||||
return $this->onec;
|
return $this->onec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -498,7 +499,8 @@ class Supply extends Product implements ProductInterface, OfferInterface
|
||||||
* @param $types
|
* @param $types
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function createPriceTypes1c($types) {
|
public static function createPriceTypes1c($types)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -511,8 +513,8 @@ class Supply extends Product implements ProductInterface, OfferInterface
|
||||||
* @param \Zenwalker\CommerceML\Model\Simple $specification
|
* @param \Zenwalker\CommerceML\Model\Simple $specification
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setSpecification1c($specification) {
|
public function setSpecification1c($specification)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -572,4 +574,43 @@ class Supply extends Product implements ProductInterface, OfferInterface
|
||||||
|
|
||||||
return SupplyEdgeProduct::search($this->readId(), type: 'connect', limit: 1)['onec']['Цены']['Цена'];
|
return SupplyEdgeProduct::search($this->readId(), type: 'connect', limit: 1)['onec']['Цены']['Цена'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Найти аккаунт владельца
|
||||||
|
*
|
||||||
|
* @return Account|null Аккаунт владельца
|
||||||
|
*/
|
||||||
|
public function searchAccount(): ?array
|
||||||
|
{
|
||||||
|
return static::searchAccountById($this->_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Найти аккаунт владельца
|
||||||
|
*
|
||||||
|
* @param string|null $_id Идентификатор
|
||||||
|
*
|
||||||
|
* @return Account|null Аккаунт владельца
|
||||||
|
*/
|
||||||
|
public static function searchAccountById(string $_id): ?array
|
||||||
|
{
|
||||||
|
return static::searchByEdge(
|
||||||
|
from: 'account',
|
||||||
|
to: 'supply',
|
||||||
|
edge: 'account_edge_supply',
|
||||||
|
direction: 'INBOUND',
|
||||||
|
subquery_where: [
|
||||||
|
[
|
||||||
|
'account_edge_supply._from == account._id'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'account_edge_supply._to == "' . $_id . '"'
|
||||||
|
]
|
||||||
|
],
|
||||||
|
subquery_select: 'account',
|
||||||
|
where: 'account_edge_supply[0]._id != null',
|
||||||
|
limit: 1,
|
||||||
|
select: 'account_edge_supply[0]'
|
||||||
|
)[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,61 +12,108 @@ use app\models\City;
|
||||||
use GuzzleHttp\Client as Guzzle;
|
use GuzzleHttp\Client as Guzzle;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use phpDocumentor\Reflection\Types\Nullable;
|
||||||
|
|
||||||
class Dellin extends Model
|
class Dellin extends Model
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Инстанция браузера
|
* Инстанция браузера
|
||||||
*/
|
*/
|
||||||
public Guzzle $browser;
|
public static Guzzle $browser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Сессия аккаунта
|
* Сессия аккаунта
|
||||||
*/
|
*/
|
||||||
public string $session;
|
public static string $session;
|
||||||
|
|
||||||
public function __construct($config = [])
|
public function __construct($config = [])
|
||||||
{
|
{
|
||||||
parent::__construct($config);
|
parent::__construct($config);
|
||||||
|
|
||||||
$this->browser = new Guzzle([
|
self::$browser = new Guzzle([
|
||||||
'base_uri' => 'https://api.dellin.ru/'
|
'base_uri' => 'https://api.dellin.ru/'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->authorization();
|
self::authorization();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Поиск городов
|
// * Поиск городов
|
||||||
*
|
// *
|
||||||
* @return array|null Найденные города
|
// * @return array|null Найденные города
|
||||||
*/
|
// */
|
||||||
public function searchCities(): ?array
|
// public function searchCities(): ?array
|
||||||
{
|
// {
|
||||||
// $this->onReady(function () {
|
// $this->onReady(function () {
|
||||||
// // Запрос городов
|
// // Запрос городов
|
||||||
// $request = $this->browser->post('/v2/public/kladr.json', [
|
// $request = $this->browser->post('/v2/public/kladr.json', [
|
||||||
// 'json' => [
|
// 'json' => [
|
||||||
// 'appkey' => yii::$app->params['dellin']['key'],
|
// 'appkey' => yii::$app->params['dellin']['key'],
|
||||||
|
|
||||||
// ]
|
// ]
|
||||||
// ])
|
// ])
|
||||||
// });
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Рассчет доставки
|
||||||
|
*
|
||||||
|
* @param string $from Номер КЛАДР
|
||||||
|
* @param string $to Номер КЛАДР
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function calcDelivery(string $from, string $to): array
|
||||||
|
{
|
||||||
|
return self::handle(function () use ($from, $to) {
|
||||||
|
// Всё готово к работе
|
||||||
|
|
||||||
|
// Запрос
|
||||||
|
$request = self::$browser->post('/v1/micro_calc.json', [
|
||||||
|
'json' => [
|
||||||
|
'appkey' => yii::$app->params['dellin']['key'],
|
||||||
|
'sessionID' => self::$session,
|
||||||
|
'derival' => [
|
||||||
|
'city' => $from
|
||||||
|
],
|
||||||
|
'arrival' => [
|
||||||
|
'city' => $to
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Синхронизация городов
|
* Синхронизация городов
|
||||||
*
|
*
|
||||||
* @return array|null Найденные города
|
* @return array|null Найденные города
|
||||||
*
|
|
||||||
* @todo Написать проверку по хешу
|
|
||||||
*/
|
*/
|
||||||
public function syncCities(): ?array
|
public static function importCities(): ?int
|
||||||
{
|
{
|
||||||
return $this->ifReady(function () {
|
return self::handle(function () {
|
||||||
// Запрос ссылки на файл с городам
|
// Всё готово к работе
|
||||||
// Получаем hash и url ()
|
|
||||||
$request = $this->browser->post('/v1/public/cities.json', [
|
// Запрос ссылки на файл с городами, возвращает ['hash' => string, 'url' => string]
|
||||||
|
$request = self::$browser->post('/v1/public/cities.json', [
|
||||||
'json' => [
|
'json' => [
|
||||||
'appkey' => yii::$app->params['dellin']['key'],
|
'appkey' => yii::$app->params['dellin']['key'],
|
||||||
]
|
]
|
||||||
|
@ -77,79 +124,187 @@ class Dellin extends Model
|
||||||
|
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$response = json_decode((string) $request->getBody(), true);
|
$response = json_decode((string) $request->getBody(), true);
|
||||||
|
$hash_target = $response['hash'];
|
||||||
|
$dir = YII_PATH_PUBLIC . '/../assets/import/' . date('Y-m-d', time()) . '/dellin/cities/' . (yii::$app->user->identity->_key ?? 'system') . '/';
|
||||||
|
|
||||||
|
if (!file_exists($dir)) {
|
||||||
|
// Директории не существует
|
||||||
|
|
||||||
if ($response['metadata']['status'] === 200) {
|
mkdir($dir, 0775, true);
|
||||||
// Аутентификация и авторизация пройдены успешно
|
|
||||||
|
|
||||||
// Запись сессии
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception('Не удалось синхронизировать данные городов с ДеловыеЛинии', $response['metadata']['status']);
|
$request = self::$browser->get($response['url'], [
|
||||||
|
'sink' => $file = $dir . time() . '.csv'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Проверка хеша
|
||||||
|
if ($hash_target !== $hash_received = md5_file($file)) {
|
||||||
|
// Удалось пройти проверку на хеши файлов
|
||||||
|
|
||||||
|
// Инициализация (чтение файла)
|
||||||
|
$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 = 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);
|
||||||
throw new Exception('Не удалось синхронизировать данные городов с ДеловыеЛинии', $request->getStatusCode);
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Аутентификация и авторизация
|
* Аутентификация и авторизация
|
||||||
*/
|
*/
|
||||||
protected function authorization(): ?self
|
protected static function authorization(): bool
|
||||||
{
|
{
|
||||||
return $this->ifReady(function () {
|
// Аутентификация и авторизация
|
||||||
// Аутентификация и авторизация
|
$request = self::browser()->post('/v3/auth/login.json', [
|
||||||
$request = $this->browser->post('/v3/auth/login.json', [
|
'json' => [
|
||||||
'json' => [
|
'appkey' => yii::$app->params['dellin']['key'],
|
||||||
'appkey' => yii::$app->params['dellin']['key'],
|
'login' => yii::$app->params['dellin']['nickname'],
|
||||||
'login' => yii::$app->params['dellin']['nickname'],
|
'password' => yii::$app->params['dellin']['password']
|
||||||
'password' => yii::$app->params['dellin']['password']
|
]
|
||||||
]
|
]);
|
||||||
]);
|
|
||||||
|
|
||||||
if ($request->getStatusCode() === 200) {
|
if ($request->getStatusCode() === 200) {
|
||||||
// Запрос прошел успешно
|
// Запрос прошел успешно
|
||||||
|
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$response = json_decode((string) $request->getBody(), true);
|
$response = json_decode((string) $request->getBody(), true);
|
||||||
|
|
||||||
if ($response['metadata']['status'] === 200) {
|
if ($response['metadata']['status'] === 200) {
|
||||||
// Аутентификация и авторизация пройдены успешно
|
// Аутентификация и авторизация пройдены успешно
|
||||||
|
|
||||||
// Запись сессии
|
// Запись сессии
|
||||||
$this->session = $response['data']['sessionID'];
|
self::$session = $response['data']['sessionID'];
|
||||||
|
|
||||||
return $this;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
throw new Exception('Не удалось авторизироваться в ДеловыеЛинии', $response['metadata']['status']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new Exception('Не удалось авторизироваться в ДеловыеЛинии', $response['metadata']['status']);
|
||||||
|
}
|
||||||
|
|
||||||
throw new Exception('Не удалось авторизироваться в ДеловыеЛинии', $request->getStatusCode);
|
throw new Exception('Не удалось авторизироваться в ДеловыеЛинии', $request->getStatusCode);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Проверка на то, что браузер готов к работе
|
* Инициализация и выполнение
|
||||||
*
|
*
|
||||||
* @param callable $function Код к выполнению
|
* @param callable|null $function Код к выполнению
|
||||||
* @param [type] ...$vars Параметры к нему
|
* @param [mixed] ...$vars Параметры к нему
|
||||||
*
|
*
|
||||||
* @return mixed Возврат из функции
|
* @return mixed Возврат из функции
|
||||||
*/
|
*/
|
||||||
protected function ifReady(callable $function, ...$vars): mixed
|
protected static function handle(callable $function = null, mixed ...$vars): mixed
|
||||||
{
|
{
|
||||||
if (isset($this->browser)) {
|
try {
|
||||||
// Браузер инициализирован
|
if (self::browser() instanceof Guzzle) {
|
||||||
|
// Браузер инициализирован
|
||||||
|
|
||||||
return $function(...$vars);
|
if (self::authorization() && isset(self::$session)) {
|
||||||
|
// Аутентифицирован и авторизован
|
||||||
|
|
||||||
|
return $function(...$vars);
|
||||||
|
} else {
|
||||||
|
throw new Exception('Аккаунт не авторизирован', 401);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Exception('Браузер не инициализирован', 500);
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
throw new Exception($e->getMessage(), 500, $e->getPrevious());
|
||||||
|
// throw new Exception('Не удалось инициализировать инстанцию для работы с API ДеловыеЛинии', 500, $e->getPrevious());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
throw new Exception('Браузер не инициализирован', 500);
|
/**
|
||||||
|
* Чтение или инициализация браузера
|
||||||
|
*
|
||||||
|
* @return Guzzle Инстанция
|
||||||
|
*/
|
||||||
|
protected static function browser(): Guzzle
|
||||||
|
{
|
||||||
|
return self::$browser ?? self::$browser = new Guzzle([
|
||||||
|
'base_uri' => 'https://api.dellin.ru/'
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,17 @@ namespace app\models\traits;
|
||||||
|
|
||||||
use yii;
|
use yii;
|
||||||
|
|
||||||
use exception;
|
use ArangoDBClient\Document;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
trait SearchByEdge
|
trait SearchByEdge
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Поиск через связи рёбрами с аккаунтом
|
* Поиск через связи рёбрами с аккаунтом
|
||||||
*
|
*
|
||||||
|
* Аргумент $asArray и его реализацию пришлось добавить чтобы не переписывать кучу кода
|
||||||
|
*
|
||||||
* @param string $id Идентификатор пользователя
|
* @param string $id Идентификатор пользователя
|
||||||
* @param int $limit Количество
|
* @param int $limit Количество
|
||||||
* @param int $offset Сдвиг
|
* @param int $offset Сдвиг
|
||||||
|
@ -27,12 +31,15 @@ trait SearchByEdge
|
||||||
int|null $offset = 0,
|
int|null $offset = 0,
|
||||||
array $sort = ['ASC'],
|
array $sort = ['ASC'],
|
||||||
string|array $subquery_where = [],
|
string|array $subquery_where = [],
|
||||||
|
string|array $subquery_select = null,
|
||||||
array $foreach = [],
|
array $foreach = [],
|
||||||
string|array $where = [],
|
string|array $where = [],
|
||||||
array|null $let = [],
|
array|null $let = [],
|
||||||
string|array $select = null,
|
string|array $select = null,
|
||||||
callable|null $handle = null,
|
callable|null $handle = null,
|
||||||
array $params = []
|
array $params = [],
|
||||||
|
bool $asArray = true,
|
||||||
|
bool $debug = false
|
||||||
): mixed {
|
): mixed {
|
||||||
$subquery = static::find()
|
$subquery = static::find()
|
||||||
->params($params)
|
->params($params)
|
||||||
|
@ -42,7 +49,7 @@ trait SearchByEdge
|
||||||
->where($subquery_where);
|
->where($subquery_where);
|
||||||
|
|
||||||
$subquery = $subquery
|
$subquery = $subquery
|
||||||
->select($edge ?? $from . '_edge_' . $to)
|
->select($subquery_select ?? $edge ?? $from . '_edge_' . $to)
|
||||||
->createCommand();
|
->createCommand();
|
||||||
|
|
||||||
$query = static::find()
|
$query = static::find()
|
||||||
|
@ -58,12 +65,20 @@ trait SearchByEdge
|
||||||
$query->let(...$let);
|
$query->let(...$let);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Запрос
|
// Инициализация
|
||||||
$request = $query
|
$request = $query
|
||||||
->foreach($foreach)
|
->foreach($foreach)
|
||||||
->where($where)
|
->where($where)
|
||||||
->select($select ?? $to);
|
->select($select ?? $to);
|
||||||
|
|
||||||
|
// Режим проверки
|
||||||
|
if ($debug) {
|
||||||
|
// Запрошена проверка
|
||||||
|
|
||||||
|
return (string) $request->createCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запрос
|
||||||
if (isset($handle)) {
|
if (isset($handle)) {
|
||||||
// Передана функция для постобработки
|
// Передана функция для постобработки
|
||||||
|
|
||||||
|
@ -71,14 +86,27 @@ trait SearchByEdge
|
||||||
} else if (isset($select)) {
|
} else if (isset($select)) {
|
||||||
$response = $request->createCommand()->execute()->getAll();
|
$response = $request->createCommand()->execute()->getAll();
|
||||||
|
|
||||||
foreach ($response as &$attribute) {
|
if ($asArray) {
|
||||||
// Приведение всех свойств в массив и очистка от лишних данных
|
// Передан параметр указывающий на необходимость возврата как объекта
|
||||||
|
|
||||||
$attribute = $attribute->getAll();
|
// Очистка
|
||||||
|
foreach ($response as &$attribute) {
|
||||||
|
// Приведение всех свойств в массив и очистка от лишних данных
|
||||||
|
|
||||||
|
if ($attribute instanceof Document) {
|
||||||
|
// Получена инстанция документа ArangoDB
|
||||||
|
|
||||||
|
$attribute = $attribute->getAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
} else {
|
} else {
|
||||||
|
if ($limit === 1) {
|
||||||
|
return $request->one();
|
||||||
|
}
|
||||||
|
|
||||||
return $request->all();
|
return $request->all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use app\models\Product;
|
||||||
<article class="col-12">
|
<article class="col-12">
|
||||||
<div class="p-3 d-flex flex-column rounded">
|
<div class="p-3 d-flex flex-column rounded">
|
||||||
<div id="product_slider" class="row px-3 profile_panel">
|
<div id="product_slider" class="row px-3 profile_panel">
|
||||||
<div class="col-1 product_slider_preview p-0 pr-3 mb-3">
|
<div class="col-1 product_slider_preview p-0 pr-3 mb-3 d-flex flex-column">
|
||||||
<?php
|
<?php
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$covr_not_found = true;
|
$covr_not_found = true;
|
||||||
|
@ -157,37 +157,40 @@ use app\models\Product;
|
||||||
|
|
||||||
<div class="dropdown-divider px-0 mb-2"></div>
|
<div class="dropdown-divider px-0 mb-2"></div>
|
||||||
|
|
||||||
|
<!-- Информация о товаре -->
|
||||||
|
|
||||||
<?php if (
|
<?php if (
|
||||||
!yii::$app->user->isGuest
|
!yii::$app->user->isGuest
|
||||||
&& (yii::$app->user->identity->type === 'administrator'
|
&& (yii::$app->user->identity->type === 'administrator'
|
||||||
|| yii::$app->user->identity->type === 'moderator')
|
|| yii::$app->user->identity->type === 'moderator')
|
||||||
) : ?>
|
) : ?>
|
||||||
<section id="prod_<?= $model['catn'] ?>_info" class="col mb-1">
|
<section id="prod_<?= $model['catn'] ?>_info" class="col">
|
||||||
<p class="form-control-sm">
|
<!-- Габариты -->
|
||||||
<b class="mr-1">Габариты:</b>
|
<p class="form-control-sm p-0 h-auto">
|
||||||
<span id="prod_<?= $model['catn'] ?>_dmns_x" class="ml-1 pointer-event" role="button" onclick="return product_panel_dimensions_edit('<?= $model['catn'] ?>', this, 'x');"><?= empty($model['dmns']['x']) ? '0' : $model['dmns']['x'] ?></span>
|
<b>Габариты:</b><span id="prod_<?= $model['catn'] ?>_dmns_x" class="ml-1 pointer-event" role="button" onclick="return product_panel_dimensions_edit('<?= $model['catn'] ?>', this, 'x');"><?= empty($model['dmns']['x']) ? '0' : $model['dmns']['x'] ?></span><span class="mr-1">см</span><small>x</small><span id="prod_<?= $model['catn'] ?>_dmns_y" class="ml-1 pointer-event" role="button" onclick="return product_panel_dimensions_edit('<?= $model['catn'] ?>', this, 'y');"><?= empty($model['dmns']['y']) ? '0' : $model['dmns']['y'] ?></span><span class="mr-1">см</span><small>x</small><span id="prod_<?= $model['catn'] ?>_dmns_z" class="ml-1 pointer-event" role="button" onclick="return product_panel_dimensions_edit('<?= $model['catn'] ?>', this, 'z');"><?= empty($model['dmns']['z']) ? '0' : $model['dmns']['z'] ?></span><span class="mr-1">см</span>
|
||||||
<span class="mr-1">см</span>
|
</p>
|
||||||
<small>x</small>
|
<!-- Вес -->
|
||||||
<span id="prod_<?= $model['catn'] ?>_dmns_y" class="ml-1 pointer-event" role="button" onclick="return product_panel_dimensions_edit('<?= $model['catn'] ?>', this, 'y');"><?= empty($model['dmns']['y']) ? '0' : $model['dmns']['y'] ?></span>
|
<p class="form-control-sm p-0 h-auto">
|
||||||
<span class="mr-1">см</span>
|
<b>Вес:</b><span id="prod_<?= $model['catn'] ?>_dmns_x" class="ml-1 pointer-event" role="button" onclick="return product_panel_weight_edit('<?= $model['catn'] ?>', this);"><?= empty($model['wght']) ? '0' : $model['wght'] ?></span><span class="mr-1">кг</span>
|
||||||
<small>x</small>
|
|
||||||
<span id="prod_<?= $model['catn'] ?>_dmns_z" class="ml-1 pointer-event" role="button" onclick="return product_panel_dimensions_edit('<?= $model['catn'] ?>', this, 'z');"><?= empty($model['dmns']['z']) ? '0' : $model['dmns']['z'] ?></span>
|
|
||||||
<span class="mr-1">см</span>
|
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
<?php else : ?>
|
<?php else : ?>
|
||||||
<section id="prod_<?= $model['catn'] ?>_info" class="col mb-1">
|
<section id="prod_<?= $model['catn'] ?>_info" class="col mb-1">
|
||||||
<p class="form-control-sm">
|
<!-- Габариты -->
|
||||||
<b class="mr-1">Габариты:</b>
|
<p class="form-control-sm p-0 h-auto">
|
||||||
<span id="prod_<?= $model['catn'] ?>_dmns_x" class="mx-1"><?= $model['dmns']['x'] ?? '0' ?></span>
|
<b>Габариты:</b><span id="prod_<?= $model['catn'] ?>_dmns_x" class="ml-1"><?= empty($model['dmns']['x']) ? '0' : $model['dmns']['x'] ?></span><span class="mr-1">см</span><small>x</small><span id="prod_<?= $model['catn'] ?>_dmns_y" class="ml-1"><?= empty($model['dmns']['y']) ? '0' : $model['dmns']['y'] ?></span><span class="mr-1">см</span><small>x</small><span id="prod_<?= $model['catn'] ?>_dmns_z" class="ml-1"><?= empty($model['dmns']['z']) ? '0' : $model['dmns']['z'] ?></span><span class="mr-1">см</span>
|
||||||
<small>x</small>
|
</p>
|
||||||
<span id="prod_<?= $model['catn'] ?>_dmns_y" class="mx-1"><?= $model['dmns']['y'] ?? '0' ?></span>
|
<!-- Вес -->
|
||||||
<small>x</small>
|
<p class="form-control-sm p-0 h-auto">
|
||||||
<span id="prod_<?= $model['catn'] ?>_dmns_z" class="mx-1"><?= $model['dmns']['z'] ?? '0' ?></span>
|
<b>Габариты:</b><span id="prod_<?= $model['catn'] ?>_dmns_x" class="ml-1"><?= empty($model['wght']) ? '0' : $model['wght'] ?></span><small>кг</small>
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
|
<div class="dropdown-divider px-0 mb-2"></div>
|
||||||
|
|
||||||
|
<!-- Описание -->
|
||||||
|
|
||||||
<div class="row mb-3 h-100 product_panel d-flex flex-column">
|
<div class="row mb-3 h-100 product_panel d-flex flex-column">
|
||||||
<?php if (
|
<?php if (
|
||||||
!yii::$app->user->isGuest
|
!yii::$app->user->isGuest
|
||||||
|
@ -260,4 +263,4 @@ use app\models\Product;
|
||||||
|| yii::$app->user->identity->type === 'moderator')
|
|| yii::$app->user->identity->type === 'moderator')
|
||||||
) : ?>
|
) : ?>
|
||||||
<script src="/js/product_panel.js" defer></script>
|
<script src="/js/product_panel.js" defer></script>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
|
@ -40,7 +40,8 @@ if (
|
||||||
<?php if (!yii::$app->user->isGuest) : ?>
|
<?php if (!yii::$app->user->isGuest) : ?>
|
||||||
<input type="radio" id="profile_panel_settings_account" name="main_panel" <?= $panel === 'profile_panel_settings_account' ? 'checked' : null ?> />
|
<input type="radio" id="profile_panel_settings_account" name="main_panel" <?= $panel === 'profile_panel_settings_account' ? 'checked' : null ?> />
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h5>Основная информация</h5>
|
<h5>Доставка</h5>
|
||||||
|
<div class="dropdown-divider mb-3"></div>
|
||||||
<?php $form = ActiveForm::begin([
|
<?php $form = ActiveForm::begin([
|
||||||
'id' => 'form_profile_settings',
|
'id' => 'form_profile_settings',
|
||||||
'action' => false,
|
'action' => false,
|
||||||
|
@ -54,15 +55,15 @@ if (
|
||||||
|
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$model ?? $model = yii::$app->user->identity;
|
$model ?? $model = yii::$app->user->identity;
|
||||||
$account_sections_city_list or $account_sections_city_list = ['Нет данных'];
|
$delivery_to_city_list or $delivery_to_city_list = ['Нет данных'];
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<?= $form->field($model, 'opts[account_sections_city]', ['options' => ['class' => "mb-1"]])
|
<?= $form->field($model, 'opts[delivery_to_city]', ['options' => ['class' => "mb-1"]])
|
||||||
->dropDownList($account_sections_city_list, [
|
->dropDownList($delivery_to_city_list, [
|
||||||
'onChange' => 'page_profile_settings(this.parentElement.parentElement, \'profile_panel_settings_account\')'
|
'onChange' => 'page_profile_settings(this.parentElement.parentElement, \'profile_panel_settings_account\')'
|
||||||
])->label('Город'); ?>
|
])->label('Город'); ?>
|
||||||
|
|
||||||
<small class="d-block mb-1">Выберите город для <b>рассчёта доставки</b></small>
|
<small class="d-block mb-1">Выберите город <b><u>получателя</u></b> для <b>рассчёта доставки</b></small>
|
||||||
|
|
||||||
<?php ActiveForm::end(); ?>
|
<?php ActiveForm::end(); ?>
|
||||||
</div>
|
</div>
|
||||||
|
@ -70,7 +71,32 @@ if (
|
||||||
<?php if (yii::$app->user->identity->agnt) : ?>
|
<?php if (yii::$app->user->identity->agnt) : ?>
|
||||||
<input type="radio" id="profile_panel_settings_company" name="main_panel" <?= $panel === 'profile_panel_settings_company' ? 'checked' : null ?> />
|
<input type="radio" id="profile_panel_settings_company" name="main_panel" <?= $panel === 'profile_panel_settings_company' ? 'checked' : null ?> />
|
||||||
<div class="col">
|
<div class="col">
|
||||||
2
|
<h5>Доставка</h5>
|
||||||
|
<div class="dropdown-divider mb-3"></div>
|
||||||
|
<?php $form = ActiveForm::begin([
|
||||||
|
'id' => 'form_profile_settings',
|
||||||
|
'action' => false,
|
||||||
|
'fieldConfig' => [
|
||||||
|
'template' => '{label}{input}',
|
||||||
|
],
|
||||||
|
'options' => [
|
||||||
|
'onsubmit' => 'return false;'
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Инициализация
|
||||||
|
$model ?? $model = yii::$app->user->identity;
|
||||||
|
$delivery_from_city_list or $delivery_from_city_list = ['Нет данных'];
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?= $form->field($model, 'opts[delivery_from_city]', ['options' => ['class' => "mb-1"]])
|
||||||
|
->dropDownList($delivery_from_city_list, [
|
||||||
|
'onChange' => 'page_profile_settings(this.parentElement.parentElement, \'profile_panel_settings_company\')'
|
||||||
|
])->label('Город'); ?>
|
||||||
|
|
||||||
|
<small class="d-block mb-1">Выберите город <b><u>отправителя</u></b> для <b>рассчёта доставки</b></small>
|
||||||
|
|
||||||
|
<?php ActiveForm::end(); ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="radio" id="profile_panel_settings_import" name="main_panel" <?= $panel === 'profile_panel_settings_import' ? 'checked' : null ?> />
|
<input type="radio" id="profile_panel_settings_import" name="main_panel" <?= $panel === 'profile_panel_settings_import' ? 'checked' : null ?> />
|
||||||
|
@ -90,13 +116,13 @@ if (
|
||||||
|
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$model ?? $model = yii::$app->user->identity;
|
$model ?? $model = yii::$app->user->identity;
|
||||||
$import_sections_oem_list or $import_sections_oem_list = ['Нет данных'];
|
$import_oem_list or $import_oem_list = ['Нет данных'];
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<?= $form->field($model, 'opts[import_sections_oem]', ['options' => ['class' => "mb-1"]])
|
<?= $form->field($model, 'opts[import_supplies_oem]', ['options' => ['class' => "mb-1"]])
|
||||||
->dropDownList($import_sections_oem_list, [
|
->dropDownList($import_oem_list, [
|
||||||
'onChange' => 'page_profile_settings(this.parentElement.parentElement, \'profile_panel_settings_import\')',
|
'onChange' => 'page_profile_settings(this.parentElement.parentElement, \'profile_panel_settings_import\')',
|
||||||
'disabled' => count($import_sections_oem_list) <= 1
|
'disabled' => count($import_oem_list) <= 1
|
||||||
])->label('OEM-номера'); ?>
|
])->label('OEM-номера'); ?>
|
||||||
|
|
||||||
<small class="d-block mb-1">Выберите поле в котором хранятся <b>ОЕМ-номера</b> и повторите импорт</small>
|
<small class="d-block mb-1">Выберите поле в котором хранятся <b>ОЕМ-номера</b> и повторите импорт</small>
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
<?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">
|
||||||
|
@ -72,43 +80,51 @@
|
||||||
|
|
||||||
// Инициализация количества
|
// Инициализация количества
|
||||||
$amount_raw = $amount = $supply['amnt'] ?? $supply['onec']['Количество'];
|
$amount_raw = $amount = $supply['amnt'] ?? $supply['onec']['Количество'];
|
||||||
|
|
||||||
if (empty($amount_raw) || $amount_raw < 1) {
|
if (empty($amount_raw) || $amount_raw < 1) {
|
||||||
|
// Уже не используется
|
||||||
$amount = 'Под заказ';
|
$amount = 'Под заказ';
|
||||||
} else {
|
} else {
|
||||||
$amount .= ' шт';
|
$amount .= ' шт';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Инициализация доставки
|
||||||
|
$delivery = Dellin::calcDelivery($supply['account']['opts']['delivery_from_city'], yii::$app->user->identity->opts['delivery_to_city'])['terminals_standard'];
|
||||||
|
$delivery_max = $delivery['period_to'] ?? 'Неизвестно';
|
||||||
|
$delivery_price = $delivery['price'] ?? 'Неизвестно';
|
||||||
|
|
||||||
if ($amount_raw < 1 || $price_raw < 1) {
|
if ($amount_raw < 1 || $price_raw < 1) {
|
||||||
// Нет в наличии или цена 0 рублей
|
// Нет в наличии или цена 0 рублей
|
||||||
|
|
||||||
$button_cart = <<<HTML
|
$supplies_html .= <<<HTML
|
||||||
<div class="col-1 h-100 text-dark d-flex" title="Товар недоступен">
|
<div class="row my-auto m-0 h-100 text-right">
|
||||||
|
<a class="col-auto ml-auto my-auto text-dark" href="/order/new/custom" role="button" onclick="return false;">
|
||||||
|
<small>
|
||||||
|
Заказать поиск у оператора
|
||||||
|
</small>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
HTML;
|
HTML;
|
||||||
} else {
|
} else {
|
||||||
$button_cart = <<<HTML
|
// Есть в наличии
|
||||||
<a class="col-1 h-100 text-dark d-flex button_white rounded" title="Добавить $catn в корзину" href="/cart" role="button" onclick="return cart_write('$catn');">
|
|
||||||
<i class="fas fa-cart-arrow-down pr-1 m-auto"></i>
|
$supplies_html .= <<<HTML
|
||||||
</a>
|
<div class="row my-auto m-0 h-100 text-right">
|
||||||
|
<small class="col-2 my-auto ml-auto">
|
||||||
|
$amount
|
||||||
|
</small>
|
||||||
|
<small class="col-2 my-auto ml-1">
|
||||||
|
$delivery_max дней<br/>
|
||||||
|
$delivery_price рублей
|
||||||
|
</small>
|
||||||
|
<b class="col-2 my-auto">
|
||||||
|
$price
|
||||||
|
</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');">
|
||||||
|
<i class="fas fa-cart-arrow-down pr-1 m-auto"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
HTML;
|
HTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
$supplies_html .= <<<HTML
|
|
||||||
<div class="row my-auto m-0 h-100 text-right">
|
|
||||||
<small class="col-2 my-auto ml-auto">
|
|
||||||
$amount
|
|
||||||
</small>
|
|
||||||
<small class="col-2 my-auto ml-1">
|
|
||||||
Доставка
|
|
||||||
</small>
|
|
||||||
<b class="col-2 my-auto">
|
|
||||||
$price
|
|
||||||
</b>
|
|
||||||
$button_cart
|
|
||||||
</div>
|
|
||||||
HTML;
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
|
@ -171,4 +187,4 @@
|
||||||
|| yii::$app->user->identity->type === 'moderator')
|
|| yii::$app->user->identity->type === 'moderator')
|
||||||
) : ?>
|
) : ?>
|
||||||
<script src="/js/product_panel.js" defer></script>
|
<script src="/js/product_panel.js" defer></script>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
|
@ -171,6 +171,76 @@ function product_panel_dimensions_save(catn, element, dimension) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function product_panel_weight_edit(catn, element) {
|
||||||
|
if (catn !== null && catn !== undefined && element !== null && element !== undefined) {
|
||||||
|
|
||||||
|
let input = document.createElement('input');
|
||||||
|
|
||||||
|
input.setAttribute('id', element.id);
|
||||||
|
input.setAttribute('class', 'ml-1 text-center product_options_edit_small');
|
||||||
|
input.setAttribute('type', 'number');
|
||||||
|
input.setAttribute('value', element.innerText);
|
||||||
|
input.setAttribute('aria-invalid', 'false');
|
||||||
|
|
||||||
|
element.replaceWith(input);
|
||||||
|
|
||||||
|
product_panel_handler_save(product_panel_weight_save, catn, input);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function product_panel_weight_save(catn, element) {
|
||||||
|
if (catn !== null && catn !== undefined && element !== null && element !== undefined) {
|
||||||
|
// Инициализация
|
||||||
|
let text = element.value;
|
||||||
|
let span = document.createElement('span');
|
||||||
|
|
||||||
|
span.setAttribute('id', element.id);
|
||||||
|
span.setAttribute('class', 'ml-1 pointer-event');
|
||||||
|
span.setAttribute('role', 'button');
|
||||||
|
span.setAttribute('onclick', 'return product_panel_weight_edit(\'' + catn + '\', this);');
|
||||||
|
|
||||||
|
if (text.length === 0) {
|
||||||
|
text = '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
span.innerText = text;
|
||||||
|
|
||||||
|
element.replaceWith(span);
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/product/' + catn + '/edit/wght',
|
||||||
|
type: 'post',
|
||||||
|
dataType: 'json',
|
||||||
|
data: {
|
||||||
|
'_csrf': yii.getCsrfToken(),
|
||||||
|
'text': text
|
||||||
|
},
|
||||||
|
success: function (data, status) {
|
||||||
|
// Заголовок
|
||||||
|
if (data.weight !== undefined && span !== null && span !== undefined) {
|
||||||
|
// Обновление заголовка
|
||||||
|
span.innerText = data.weight;
|
||||||
|
|
||||||
|
// Запись аттрибута
|
||||||
|
span.setAttribute('onclick', 'return product_panel_weight_edit(\'' + catn + '\', this);');
|
||||||
|
};
|
||||||
|
|
||||||
|
product_response_success(data, status);
|
||||||
|
},
|
||||||
|
error: product_response_error
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
function product_panel_description_edit(catn, element) {
|
function product_panel_description_edit(catn, element) {
|
||||||
if (catn !== null && catn !== undefined && element !== null && element !== undefined) {
|
if (catn !== null && catn !== undefined && element !== null && element !== undefined) {
|
||||||
element.innerHTML = '<textarea class="form-control" cols="50" rows="5" onchange = "return product_panel_description_save(\'' + catn + '\', this.parentElement)">' + element.innerText + '</textarea>';
|
element.innerHTML = '<textarea class="form-control" cols="50" rows="5" onchange = "return product_panel_description_save(\'' + catn + '\', this.parentElement)">' + element.innerText + '</textarea>';
|
||||||
|
@ -301,4 +371,4 @@ function product_panel_handler_save(save, catn, element, ...vars) {
|
||||||
|
|
||||||
document.body.addEventListener('click', product_panel_handler_save_function, true);
|
document.body.addEventListener('click', product_panel_handler_save_function, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
defined('YII_DEBUG') or define('YII_DEBUG', true);
|
defined('YII_DEBUG') or define('YII_DEBUG', true);
|
||||||
defined('YII_ENV') or define('YII_ENV', 'dev');
|
defined('YII_ENV') or define('YII_ENV', 'dev');
|
||||||
|
defined('YII_PATH_PUBLIC') or define('YII_PATH_PUBLIC', __DIR__ . '/web');
|
||||||
|
|
||||||
require __DIR__ . '../../../../vendor/autoload.php';
|
require __DIR__ . '../../../../vendor/autoload.php';
|
||||||
require __DIR__ . '../../../../vendor/yiisoft/yii2/Yii.php';
|
require __DIR__ . '../../../../vendor/yiisoft/yii2/Yii.php';
|
||||||
|
|
Reference in New Issue