Доработка поиска, поиск аттрибутов

This commit is contained in:
RedHood 2021-01-31 11:31:22 +10:00
parent 5d18c95dc4
commit 25709ee380
16 changed files with 656 additions and 250 deletions

View File

@ -22,11 +22,9 @@ class MainController extends Controller
}
/**
* Displays homepage.
*
* @return string
* Главная страница
*/
public function actionIndex()
public function actionIndex(): string|array
{
if (Yii::$app->request->isAjax) {
// AJAX-POST-запрос

View File

@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace app\controllers;
@ -8,6 +9,7 @@ use yii\web\Controller;
use yii\web\Response;
use yii\web\Cookie;
use yii\web\UploadedFile;
use app\models\Supply;
use app\models\SupplyGroup;
@ -56,10 +58,16 @@ class ProfileController extends Controller
]);
}
public function actionIndex()
/**
* Страница с настройками аккаунта
*/
public function actionIndex(): string|array
{
// Инициализация
$model = new Supply(Yii::$app->request->post('Supply') ?? Yii::$app->request->get('Supply'));
$model = Yii::$app->user->identity;
// Генерация
$sidebar = $this->renderPartial('sidebar');
if (Yii::$app->request->isAjax) {
// AJAX-POST-запрос
@ -67,13 +75,39 @@ class ProfileController extends Controller
Yii::$app->response->format = Response::FORMAT_JSON;
return [
'main' => $this->renderPartial('index'),
'main' => $this->renderPartial('index', compact('model', 'sidebar')),
'redirect' => '/profile',
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
return $this->render('index', compact('model'));
return $this->render('index', compact('model', 'sidebar'));
}
/**
* Страницка поставок
*/
public function actionSupplies(): string|array
{
// Инициализация
$model = new Supply(Yii::$app->request->post('Supply') ?? Yii::$app->request->get('Supply'));
// Генерация
$sidebar = $this->renderPartial('sidebar', compact('model'));
if (Yii::$app->request->isAjax) {
// AJAX-POST-запрос
Yii::$app->response->format = Response::FORMAT_JSON;
return [
'main' => $this->renderPartial('supplies', compact('model', 'sidebar')),
'redirect' => '/profile/supplies',
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
return $this->render('supplies', compact('model', 'sidebar'));
}
public function actionImport()
@ -82,6 +116,9 @@ class ProfileController extends Controller
$model = new Supply(Yii::$app->request->post('Supply') ?? Yii::$app->request->get('Supply'));
$model->scenario = $model::SCENARIO_IMPORT;
// Генерация
$sidebar = $this->renderPartial('sidebar', compact('model'));
if (Yii::$app->request->isAjax) {
// AJAX-POST-запрос
@ -94,12 +131,12 @@ class ProfileController extends Controller
}
return [
'main' => $this->renderPartial('index', compact('model')),
'main' => $this->renderPartial('supplies', compact('model', 'sidebar')),
'_csrf' => Yii::$app->request->getCsrfToken()
];
}
return $this->render('index', compact('model'));
return $this->render('supplies', compact('model', 'sidebar'));
}
public static function readGroups()

View File

@ -13,7 +13,7 @@ class SearchController extends Controller
public function actionIndex(): array|string
{
// Инициализация
$request = Yii::$app->request->post('request') ?? Yii::$app->request->get('q');
$query = Yii::$app->request->post('request') ?? Yii::$app->request->get('q');
if (Yii::$app->request->post('type') === 'product' || Yii::$app->request->get('type') === 'product') {
// Поиск по продуктам
@ -51,8 +51,10 @@ class SearchController extends Controller
// Здесь запись истории запросов (в базе данных)
//
if ($response = Product::search($request)) {
// Данные найдены
$limit = Yii::$app->request->isAjax ? 10 : 30;
if ($response = Product::searchByCatn($query, $limit)) {
// Данные найдены по поиску в полях Каталожного номера
// Запись ответа
$return = [
@ -66,9 +68,10 @@ class SearchController extends Controller
// Запись ответа
$return['main'] = $this->renderPartial('/search/index', compact('response'));
$return['search_line_window_hide'] = 1;
$return['redirect'] = '/search?type=product&q=' . $request;
$return['redirect'] = '/search?type=product&q=' . $query;
}
} else {
// Данные не найдены
Yii::$app->response->statusCode = 404;

View File

@ -1,23 +1,39 @@
<?php
declare(strict_types=1);
namespace app\models;
use Yii;
use yii\web\IdentityInterface;
use carono\exchange1c\interfaces\PartnerInterface;
/**
* Аккаунт
*
* Реализует аккаунты пользователей и поставщиков
*/
class Account extends Document implements IdentityInterface, PartnerInterface
{
public static function collectionName()
public $opts;
/**
* Имя коллекции
*/
public static function collectionName(): string
{
return 'account';
}
public function attributes()
/**
* Свойства
*/
public function attributes(): array
{
return array_merge(
parent::attributes(),
[
'auth',
'mail',
'pswd',
'name',
@ -25,12 +41,38 @@ class Account extends Document implements IdentityInterface, PartnerInterface
'sity',
'comp',
'taxn',
'auth'
'onec',
'opts'
]
);
}
public function rules()
/**
* Метки свойств
*/
public function attributeLabels(): array
{
return array_merge(
parent::attributeLabels(),
[
'auth' => 'Аутентификационный хеш',
'mail' => 'Почта',
'pswd' => 'Пароль',
'name' => 'Имя',
'simc' => 'Номер',
'sity' => 'Город',
'comp' => 'Компания',
'taxn' => 'ИНН',
'onec' => 'Данные 1C',
'opts' => 'Параметры'
]
);
}
/**
* Правила
*/
public function rules(): array
{
return array_merge(
parent::rules(),
@ -42,24 +84,13 @@ class Account extends Document implements IdentityInterface, PartnerInterface
);
}
public function attributeLabels()
{
return array_merge(
parent::attributeLabels(),
[
'mail' => 'Почта',
'pswd' => 'Пароль',
'name' => 'Имя',
'simc' => 'Номер',
'sity' => 'Город',
'comp' => 'Компания',
'taxn' => 'ИНН',
'auth' => 'Аутентификационный хеш'
]
);
}
public function beforeSave($data)
/**
* Перед сохранением
*
* @todo Подождать обновление от ебаного Yii2 и добавить
* проверку типов передаваемых параметров
*/
public function beforeSave($data): bool
{
if (parent::beforeSave($data)) {
if ($this->isNewRecord) {
@ -71,70 +102,143 @@ class Account extends Document implements IdentityInterface, PartnerInterface
return false;
}
public function getExportFields1c($context = null)
/**
* Чтение полей для экспорта из 1С
*/
public function getExportFields1c($context = null): array
{
return [
'Ид' => 'id',
'Наименование' => 'username',
'ПолноеНаименование' => 'full_name',
'Фамилия' => 'surname',
'Имя' => 'name',
];
return [];
}
/**
* Чтение идентификатора
*
* @see IdentityInterface
*/
public function getId(): string
{
return $this->_key;
return self::collectionName() . '/' . $this->_key;
}
/**
* Чтение идентификатора
*/
public function readId(): string
{
return self::collectionName() . '/' . $this->getId();
return $this->getId();
}
public function getAuthKey()
/**
* Чтение аутентификационного ключа
*/
public function getAuthKey(): string
{
return $this->auth;
}
public static function findIdentity($_key)
/**
* Идентификация
*
* @todo Подождать обновление от ебаного Yii2 и добавить
* проверку типов передаваемых параметров
*/
public static function findIdentity($_id): self
{
return static::findByKey($_key);
return static::findById($_id);
}
public static function findIdentityByAccessToken($pass, $type = null)
/**
* Поиск по ключу
*
* @todo Подождать обновление от ебаного Yii2 и добавить
* проверку типов передаваемых параметров
*/
public static function findIdentityByAccessToken($pass, $type = null): self
{
return static::findOne(['pass' => $pass]);
}
public static function findByMail($mail)
/**
* Поиск по почте
*
* @todo Подождать обновление Yii2 и добавить
* проверку типов передаваемых параметров
*/
public static function findByMail($mail): self
{
return static::findOne(['mail' => $mail]);
}
public static function findByKey($_key)
/**
* Поиск по идентификатору
*
* @todo Подождать обновление Yii2 и добавить
* проверку типов передаваемых параметров
*/
public static function findById($_id): self
{
return static::findOne(['_key' => $_key]);
return static::searchById($_id);
}
public static function validateMail($mail)
/**
* Проверка почты
*/
public static function validateMail(string $mail): bool
{
if (static::findByMail($mail)) {
// Почта найдена в базе данных
return false;
}
return true;
}
public function validatePassword($pswd)
return false;
}
/**
* Проверка пароля
*/
public function validatePassword(string $pswd): bool
{
return Yii::$app->security->validatePassword($pswd, $this->pswd);
}
public function validateAuthKey($auth)
/**
* Проверка аутентификационного ключа
*
* @todo Подождать обновление Yii2 и добавить
* проверку типов передаваемых параметров
*/
public function validateAuthKey($auth): bool
{
return $this->getAuthKey() === $auth;
}
/**
* Записать параметр
*
* @param string $name Название параметра
* @param mixed $value Значение параметра
*/
public function writeOption(string $name, mixed $value = null): bool
{
// Запись
$this->opts[$name] = $value;
// Отправка
return $this->save();
}
/**
* Удалить параметр
*
* @param string $name Название параметра
*/
public function deleteOption(string $name): bool
{
// Удаление
unset($this->opts[$name]);
// Отправка
return $this->save();
}
}

View File

@ -56,7 +56,7 @@ class AccountForm extends Model
$account = $this->getAccount();
if (!$account || !$account->validateMail($this->mail)) {
if (!$account || $account->validateMail($this->mail)) {
// Проверка не пройдена
$this->addError($attribute, 'Почта уже привязана');

View File

@ -1,13 +1,31 @@
<?php
declare(strict_types=1);
namespace app\models;
use Yii;
use mirzaev\yii2\arangodb\ActiveRecord;
use Exception;
/**
* Документ
*/
abstract class Document extends ActiveRecord
{
public function attributes()
/**
* Имя коллекции
*/
public static function collectionName(): string
{
return throw new Exception('Не установлено название коллекции');
}
/**
* Свойства
*/
public function attributes(): array
{
return [
'_key',
@ -16,7 +34,10 @@ abstract class Document extends ActiveRecord
];
}
public function attributeLabels()
/**
* Метки свойств
*/
public function attributeLabels(): array
{
return [
'date' => 'Дата',
@ -24,25 +45,36 @@ abstract class Document extends ActiveRecord
];
}
public function rules()
/**
* Правила
*
* @todo Добавить проверку существования аккаунта
*/
public function rules(): array
{
return [
[
'writer',
'string'
// Надо добавить проверку существования аккаунта
]
];
}
public function beforeSave($data)
/**
* Перед сохранением
*
* @todo Подождать обновление от ебаного Yii2 и добавить
* проверку типов передаваемых параметров
*/
public function beforeSave($data): bool
{
if (parent::beforeSave($data)) {
if ($this->isNewRecord) {
}
$this->date = time();
$this->writer = $this->writer ?? Yii::$app->user->identity->readId();
$this->writer = $this->writer ?? Yii::$app->user->id;
return true;
}
@ -50,11 +82,25 @@ abstract class Document extends ActiveRecord
return false;
}
/**
* Чтение идентификатора
*/
public function readId(): ?string
{
return isset($this->_key) ? static::collectionName() . '/' . $this->_key : null;
return isset($this->_key) && static::collectionName() ? static::collectionName() . '/' . $this->_key : null;
}
/**
* Поиск по идентификатору
*/
public static function searchById(string $_id): ?static
{
return static::findOne(['_id' => $_id]);
}
/**
* Чтение количества записей
*/
public static function readAmount(): int
{
return static::find()->count();

View File

@ -1,10 +1,17 @@
<?php
declare(strict_types=1);
namespace app\models;
/**
* Ребро
*/
abstract class Edge extends Document
{
public function attributes()
/**
* Свойства
*/
public function attributes(): array
{
return array_merge(
parent::attributes(),
@ -16,7 +23,10 @@ abstract class Edge extends Document
);
}
public function attributeLabels()
/**
* Метки свойств
*/
public function attributeLabels(): array
{
return array_merge(
parent::attributeLabels(),
@ -28,7 +38,10 @@ abstract class Edge extends Document
);
}
public function rules()
/**
* Правила
*/
public function rules(): array
{
return array_merge(
parent::rules(),
@ -49,10 +62,10 @@ abstract class Edge extends Document
/**
* Записать
*/
public function write(string $_from, string $_to, string $type = '', array $data = []): ?static
public static function write(string $_from, string $_to, string $type = '', array $data = []): ?static
{
// Инициализация
$edge = isset($this->_key) ? $this : new static;
$edge = new static;
// Настройка
$edge->_from = $_from;
@ -77,7 +90,14 @@ abstract class Edge extends Document
return $edge;
}
public function beforeSave($data)
/**
* Перед сохранением
*
* @todo Подождать обновление от ебаного Yii2 и добавить
* проверку типов передаваемых параметров
*/
public function beforeSave($data): bool
{
if (parent::beforeSave($data)) {
if ($this->isNewRecord) {

View File

@ -1,23 +1,52 @@
<?php
declare(strict_types=1);
namespace app\models;
use moonland\phpexcel\Excel;
use mirzaev\yii2\arangodb\Query;
/**
* Продукт (в ассортименте магазина)
*
* Представляет собой лот состоящий из предложений от поставщиков
*
* @see Supply Поставки для продуктов
*/
class Product extends Document
{
/**
* Сценарий импорта из .excel докумекнт
*/
const SCENARIO_IMPORT = 'import';
/**
* Сценарий записи товара
*/
const SCENARIO_WRITE = 'write';
public $file;
public $group;
/**
* Файл .excel для импорта товаров
*/
public Excel|null $file = null;
/**
* Группа в которой состоит товар
*/
public ProductGroup|null $group = null;
/**
* Имя коллекции
*/
public static function collectionName(): string
{
return 'product';
}
/**
* Свойства
*/
public function attributes(): array
{
return array_merge(
@ -34,6 +63,30 @@ class Product extends Document
);
}
/**
* Метки свойств
*/
public function attributeLabels(): array
{
return array_merge(
parent::attributeLabels(),
[
'name' => 'Название (name)',
'ocid' => 'Идентификатор 1C (ocid)',
'catn' => 'Каталожный номер (catn)',
'oemn' => 'OEM номера (oemn)',
// 'data' => 'Данные товара (data)',
// 'cost' => 'Цены (cost)',
// 'time' => 'Сроки доставки (time)',
'file' => 'Документ',
'group' => 'Группа'
]
);
}
/**
* Правила
*/
public function rules(): array
{
return array_merge(
@ -70,25 +123,13 @@ class Product extends Document
);
}
public function attributeLabels(): array
{
return array_merge(
parent::attributeLabels(),
[
'name' => 'Название (name)',
'ocid' => 'Идентификатор 1C (ocid)',
'catn' => 'Каталожный номер (catn)',
'oemn' => 'OEM номера (oemn)',
// 'data' => 'Данные товара (data)',
// 'cost' => 'Цены (cost)',
// 'time' => 'Сроки доставки (time)',
'file' => 'Документ',
'group' => 'Группа'
]
);
}
public function import()
/**
* Импорт товаров
*
* На данный момент обрабатывает только импорт из
* файлов с расширением .excel
*/
public function import(): bool
{
// Инициализация массива данных
$data = [];
@ -140,47 +181,15 @@ class Product extends Document
return false;
}
public static function search(string $text): array
{
return (new Query)->limit(10)->search('product_search', ['id' => '_key', 'catn' => 'catn'], ['catn' => $text], 1);
}
private static function writeEdgeBetweenGroup(string $from, string $to): bool
{
// Инициализация
$edge = new SupplyEdgeSupplyGroup();
// Настройка
$edge->_from = $from;
$edge->_to = $to;
// Запись
return $edge->save();
}
private static function writeEdgeBetweenRequisite(string $from, string $to): bool
{
// Инициализация
$edge = new SupplyEdgeRequisite();
// Настройка
$edge->_from = $from;
$edge->_to = $to;
// Запись
return $edge->save();
}
public static function readById(string $_key): ?Product
{
return self::findOne(['_key' => $_key]);
}
/**
* Поиск по каталожному номеру
*/
public static function readByCatn(string $catn): ?Product
public static function searchByCatn(string $query, int $limit = 1): Product|array|null
{
return self::findOne(['catn' => $catn]);
if ($limit <= 1) {
return static::findOne(['catn' => $query]);
}
return self::find()->limit($limit)->view('product_search', ['id' => '_key', 'catn' => 'catn'], ['catn' => $query], 'START');
}
}

View File

@ -1,26 +1,56 @@
<?php
declare(strict_types=1);
namespace app\models;
use carono\exchange1c\interfaces\GroupInterface;
use Zenwalker\CommerceML\Model\Group;
/**
* Группировка продуктов
*/
class ProductGroup extends Document implements GroupInterface
{
public static function collectionName()
/**
* Имя коллекции
*/
public static function collectionName(): string
{
return 'product_group';
}
public function attributes()
/**
* Свойства
*/
public function attributes(): array
{
return array_merge(
parent::attributes(),
['name', 'onec_id', 'onec_prnt_id']
[
'name'
]
);
}
public function rules()
/**
* Метки свойств
*/
public function attributeLabels(): array
{
return array_merge(
parent::attributeLabels(),
[
'name' => 'Название (name)'
]
);
}
/**
* Правила
*/
public function rules(): array
{
return array_merge(
parent::rules(),
@ -34,34 +64,18 @@ class ProductGroup extends Document implements GroupInterface
);
}
public function attributeLabels()
/**
* Запись члена группы
*/
public function writeMember(Product $member): ProductEdgeProductGroup
{
return array_merge(
parent::attributeLabels(),
[
'name' => 'Название (name)',
'onec_id' => 'Название 1C (onec_id)',
'onec_prnt_id' => 'Название родителя 1C (onec_prnt_id)',
]
);
}
public function writeMember(Document $member, string $group)
{
if (isset($member->_key)) {
return static::writeEdgeBetweenMember($member->collectionName() . '/' . $member->_key, $this->collectionName() . '/' . $group);
}
return false;
return ProductEdgeProductGroup::write($member->readId(), $this->readId(), 'member');
}
/**
* Создание дерева групп
* в параметр передаётся массив всех групп (import.xml > Классификатор > Группы)
* $groups[0]->parent - родительская группа
* $groups[0]->children - дочерние группы
* Запись рёбер групп
*
* @param Group[] $groups
* Создание взаимоотношений между группами по типу древовидной системы
*/
public static function createTree1c($groups): Document|null
{
@ -88,10 +102,11 @@ class ProductGroup extends Document implements GroupInterface
}
/**
* Создаём группу по модели группы CommerceML
* проверяем все дерево родителей группы, если родителя нет в базе - создаём
* Запись группы
*
* @param Group $group
* Создаём группу по модели группы CommerceML
* проверяем все дерево родителей группы,
* если родителя нет в базе - создаём
*/
public static function createByML(Group $group): static|array|null
{
@ -124,19 +139,6 @@ class ProductGroup extends Document implements GroupInterface
return $model;
}
private static function writeEdgeBetweenMember(string $from, string $to): bool
{
// Инициализация
$edge = new ProductEdgeProductGroup();
// Настройка
$edge->_from = $from;
$edge->_to = $to;
// Запись
return $edge->save();
}
private static function writeEdgeBetweenGroup(string $from, string $to): bool
{
// Инициализация

View File

@ -1,24 +1,46 @@
<?php
declare(strict_types=1);
namespace app\models;
use Yii;
use app\models\Account;
use app\models\Product;
use app\models\SupplyEdgeProduct;
use app\models\traits\Xml2Array;
use carono\exchange1c\interfaces\ProductInterface;
// class Supply extends Product implements OfferInterface
use mirzaev\yii2\arangodb\Query;
/**
* Поставка (выгрузка товаров от поставщиков)
*
* Представляет собой предложения от поставщиков которые добавляются
* в универсальные лоты товаров в асспортименте магазина
*
* @see Product Продукт (туда добавляются поставки)
*/
class Supply extends Product implements ProductInterface
{
/**
* Метод для конвертации XML в Array
*/
use Xml2Array;
/**
* Имя коллекции
*/
public static function collectionName(): string
{
return 'supply';
}
/**
* Свойства
*/
public function attributes(): array
{
return array_merge(
@ -29,29 +51,38 @@ class Supply extends Product implements ProductInterface
);
}
/**
* Метки свойств
*/
public function attributeLabels(): array
{
return array_merge(
parent::attributeLabels(),
[
'onec' => 'Данные 1C'
'onec' => 'Данные 1С'
]
);
}
/**
* После сохранения
*/
public function afterSave($data, $vars): void
{
// Запись ребра: АККАУНТ -> ПОСТАВКА
(new AccountEdgeSupply)->write(Yii::$app->user->identity->readId(), $this->readId(), 'import');
(new AccountEdgeSupply)->write(Yii::$app->user->id, $this->readId(), 'import');
}
/**
* Запись реквизитов из 1С
*/
public function setRequisite1c($name, $value): mixed
{
return true;
}
/**
* Установка группы, где находится продукт
* Запись группы из 1С
*/
public function setGroup1c($group): mixed
{
@ -64,23 +95,66 @@ class Supply extends Product implements ProductInterface
return true;
}
public static function createProperties1c($properties): mixed
/**
* Запись данных свойств по UUID 1C
*
* Ищет записанные свойства из 1C по их идентификатору и добавляет к ним
* недостающие данные. Это костыль оставшийся от реляционных баз данных
*/
public static function createProperties1c($properties): void
{
return true;
// Инициализация
$models = static::searchOnecByAccountId(Yii::$app->user->id, true);
$properties = self::xml2array($properties->xml);
foreach ($models as $model) {
// Перебор записей
// Инициализация
$changes = false;
foreach ($model->onec['ЗначенияСвойств'] as &$attribute) {
// Перебор аттрибутов
foreach ($properties as $property) {
// Перебор свойств
if ($attribute['ЗначенияСвойства']['Ид'] === $property['Свойство']['Ид']) {
// Совпадение идентификаторов
// Объединение данных
array_merge($attribute, $property);
// Запись индикатора наличия изменений
$changes = true;
}
}
}
if ($changes) {
$model->save();
}
}
}
/**
* Запись параметров из 1С
*/
public function setProperty1c($property): mixed
{
return true;
}
/**
* Запись изображений из 1С
*/
public function addImage1c($path, $caption): mixed
{
return true;
}
/**
* Запись ребра (предложения от поставки к продукту)
* Запись ребра (предложения от поставок к продуктам) из 1С
*/
public function getOffer1c($offer): SupplyEdgeProduct
{
@ -89,7 +163,7 @@ class Supply extends Product implements ProductInterface
// Разработчику библеотеки надо дать по жопе
return new SupplyEdgeProduct;
} else if (!$catn = Product::readByCatn($this->catn)) {
} else if (!$product = Product::searchByCatn($this->catn)) {
// Продукт не найден
if (!$this->initProduct()) {
@ -100,12 +174,12 @@ class Supply extends Product implements ProductInterface
}
}
$catn = Product::readByCatn($this->catn);
$product = Product::searchByCatn($this->catn);
// Запись ребра: ПОСТАВКА -> ПРОДУКТ
return (new SupplyEdgeProduct)->write(
$this->readId(),
$catn->readId(),
$product->readId(),
'sell',
[
'onec' => self::xml2array($offer->xml)
@ -114,26 +188,27 @@ class Supply extends Product implements ProductInterface
}
/**
* Создать продукт
* Запись продукта из 1С
*/
public static function createModel1c($product): self
public static function createModel1c($product): ?self
{
// Инициализация
$model = self::readByOnecId($id = (string) $product->Ид) ?? new self;
$model = self::searchByOnecId($id = (string) $product->Ид) ?? new self;
// Настройки
// Настройка
$model->ocid = $id ?? null;
$model->catn = (string) $product->Артикул;
$model->oemn = null;
$model->onec = self::xml2array($product->xml);
// Запись
$model->save();
return $model;
return $model->save() ? $model : null;
}
protected function initProduct(): bool
/**
* Инициализация продукта
*/
protected function initProduct(): ?Product
{
// Надо не забыть сделать выборку полей и ручное подключение
@ -141,7 +216,7 @@ class Supply extends Product implements ProductInterface
// Не передан каталожный номер
return false;
} else if (Product::readByCatn($this->catn)) {
} else if (Product::searchByCatn($this->catn)) {
// Продукт уже был инициализирован
return true;
@ -154,34 +229,79 @@ class Supply extends Product implements ProductInterface
$product->catn = $this->catn;
// Запись
return $product->save();
return $product->save() ? $product : null;
}
public function setPrice1c($price): void
/**
* Запись цены из 1С
*/
public function setPrice1c($price): mixed
{
return true;
}
/**
* Запись данных на случай ошибки при экспорте из 1С
*/
public function setRaw1cData($cml, $object): bool
{
return false;
return true;
}
public static function readByOnecId(string $ocid): ?Supply
/**
* Поиск по идентификатору из 1С
*
* @param string $ocid Идентификатор из 1С
*
* @return Supply|null
*/
public static function searchByOnecId(string $ocid): ?Supply
{
return self::findOne([self::getIdFieldName1c() => $ocid]);
return static::findOne([static::getIdFieldName1c() => $ocid]);
}
public function getGroup1c(): SupplyGroup
/**
* Чтение группы из 1С
*/
public function getGroup1c(): ?SupplyGroup
{
return $this->group;
}
/**
* Название поля в котором хранится ID из 1C
* Чтение названия поля в котором хранится идентификатор из 1С
*/
public static function getIdFieldName1c(): string
{
return 'ocid';
}
public static function searchOnecByAccountId(string $id, bool $full = false): array
{
$subquery = static::find()
->for(['account', 'account_edge_supply'])
->traversal('supply')->in('account_edge_supply')
->where(['account._id' => $id])
->select('account_edge_supply')
->createCommand();
$query = static::find()
->addParams($subquery->getBindVars())
->let('account_edge_supply', '(' . (string) $subquery . ')')
->where('supply._id == account_edge_supply[0]._to')
->andWhere('supply.onec["ЗначенияСвойств"] != null');
if ($full) {
// Если указан полный поиск
return $query->select('supply')->all();
}
$query = $query->select('supply.onec["ЗначенияСвойств"]')->createCommand()->execute()->getAll();
foreach ($query as &$attribute) {
$attribute = $attribute->getAll();
}
return $query;
}
}

View File

@ -1,37 +1,18 @@
<?php
declare(strict_types=1);
namespace app\models;
/**
* Группировка поставок
*/
class SupplyGroup extends ProductGroup
{
public static function collectionName()
/**
* Имя коллекции
*/
public static function collectionName(): string
{
return 'supply_group';
}
protected static function writeEdgeBetweenMember(string $from, string $to): bool
{
// Инициализация
$edge = new SupplyEdgeSupplyGroup();
// Настройка
$edge->_from = $from;
$edge->_to = $to;
// Запись
return $edge->save();
}
protected static function writeEdgeBetweenGroup(string $from, string $to): bool
{
// Инициализация
$edge = new SupplyGroupEdgeSupplyGroup();
// Настройка
$edge->_from = $from;
$edge->_to = $to;
// Запись
return $edge->save();
}
}

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use app\models\AccountForm;

View File

@ -2,7 +2,6 @@
use yii\bootstrap\ActiveForm;
use app\controllers\ProfileController;
use app\models\Product;
use app\models\Supply;
?>
@ -11,21 +10,15 @@ use app\models\Supply;
<div id="page_profile" class="container h-100">
<div class="row h-100 py-3">
<nav class="col-3">
<div class="p-3 rounded">
<div class="d-flex">
<p>Почта: </p>
<p class="ml-auto"><?php echo Yii::$app->user->identity->mail ?></p>
</div>
</div>
<?= $sidebar ?>
</nav>
<article class="col-9">
<div class="h-100 p-3 rounded">
<h4 class="ml-4">Личный кабинет</h4>
<div class="dropdown-divider"></div>
<p>Не знаю что сюда пока добавить</p>
<div class="h-100 p-4 rounded">
<h4 class="ml-4 mb-4">Настройки аккаунта</h4>
<p>Пока не сделана нормальная панель управления я просто буду добавлять все настройки сюда</p>
<?php
$form = ActiveForm::begin([
'id' => 'form_product_import_excel',
'id' => 'form_profile_options',
'action' => false,
'fieldConfig' => [
'template' => '{label}{input}',
@ -37,20 +30,26 @@ use app\models\Supply;
]
]);
$model = $model ?? new Supply;
$groups = ProfileController::readGroups();
$model = $model ?? Yii::$app->user->identity;
var_dump($attributes = Supply::searchOnecByAccountId(Yii::$app->user->id));
// $list = [];
// //
// foreach ($attributes as $attribute) {
// $id = $attribute['ЗначенияСвойства']['Ид'];
// if (in_array($id, $list, true)) {
// continue;
// }
// $list[] = $id;
// }
?>
<?= $form->field($model, 'group', ['options' => ['class' => "mb-3"]])->dropDownList($groups ?? ['Нет данных']); ?>
<?= $form->field($model, 'file', ['enableLabel' => false])->fileInput(['multiple' => true, 'onChange' => 'supply_import(this.parentElement.parentElement)']) ?>
<?= $form->errorSummary($model, ['header' => 'В документе были допущены ошибки:' /*, 'footer' => 'Исправьте их и попробуйте снова'*/]); ?>
<?= "a" //$form->field($model, 'opts[import_sections_oem]', ['options' => ['class' => "mb-3"]])->dropDownList($list ?? ['Нет данных']); ?>
<?php ActiveForm::end(); ?>
<p>Всего товаров: <?php echo Product::readAmount() ?></p>
<p>Всего поставок: <?php echo Supply::readAmount() ?></p>
</div>
</article>
</div>

View File

@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
use Yii;
use app\models\Product;
use app\models\Supply;
?>
<div class="p-3 rounded">
<div class="row px-3">
<p class="ml-0">Почта: </p>
<p class="mr-0"><?= Yii::$app->user->identity->mail ?></p>
</div>
<div class="dropdown-divider my-3"></div>
<dl class="m-0">
<dt>
<a class="row text-dark mb-3 px-3 font-weight-normal" href="/profile">Настройки аккаунта</a>
</dt>
<dt>
<a class="row text-dark px-3 font-weight-normal" href="/profile/supplies">Управление поставками</a>
</dt>
</dl>
<div class="dropdown-divider my-3"></div>
<div class="row px-3">
<p class="ml-0">Товары:</p>
<p class="mr-0"><?= Product::readAmount() ?></p>
</div>
<div class="row px-3">
<p class="ml-0">Поставки:</p>
<p class="mr-0"><?= Supply::readAmount() ?></p>
</div>
</div>

View File

@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
use yii\bootstrap\ActiveForm;
use app\controllers\ProfileController;
use app\models\Supply;
?>
<link href="/css/pages/profile.css" rel="stylesheet">
<div id="page_profile" class="container h-100">
<div class="row h-100 py-3">
<nav class="col-3">
<?= $sidebar ?>
</nav>
<article class="col-9">
<div class="h-100 p-4 rounded">
<h4 class="ml-4 mb-4">Управление поставками</h4>
<?php
$form = ActiveForm::begin([
'id' => 'form_product_import_excel',
'action' => false,
'fieldConfig' => [
'template' => '{label}{input}',
'options' => ['class' => '']
],
'options' => [
'class' => 'mb-3',
'onsubmit' => 'return false;'
]
]);
$model = $model ?? new Supply;
$groups = ProfileController::readGroups();
?>
<?= $form->field($model, 'group', ['options' => ['class' => "mb-3"]])->dropDownList($groups ?? ['Нет данных']); ?>
<?= $form->field($model, 'file', ['enableLabel' => false])->fileInput(['multiple' => true, 'onChange' => 'supply_import(this.parentElement.parentElement)']) ?>
<?= $form->errorSummary($model, ['header' => 'В документе были допущены ошибки:' /*, 'footer' => 'Исправьте их и попробуйте снова'*/]); ?>
<?php ActiveForm::end(); ?>
</div>
</article>
</div>
</div>
<script src="/js/profile.js" defer></script>