Создан импорт из 1C, без поддержки групп
This commit is contained in:
parent
94b719b67e
commit
212694c917
|
@ -12,9 +12,9 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=8.0.0",
|
"php": "^8.0.0",
|
||||||
"twbs/bootstrap": ">=4.5",
|
"twbs/bootstrap": ">=4.5",
|
||||||
"yiisoft/yii2": ">=2.0.14",
|
"yiisoft/yii2": "2.*",
|
||||||
"yiisoft/yii2-bootstrap": ">=2.0.0",
|
"yiisoft/yii2-bootstrap": ">=2.0.0",
|
||||||
"yiisoft/yii2-swiftmailer": ">=2.0.0",
|
"yiisoft/yii2-swiftmailer": ">=2.0.0",
|
||||||
"bower-asset/bootstrap": "*",
|
"bower-asset/bootstrap": "*",
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -68,12 +68,19 @@ $config = [
|
||||||
'class' => 'carono\exchange1c\ExchangeModule',
|
'class' => 'carono\exchange1c\ExchangeModule',
|
||||||
'groupClass' => 'app\models\SupplyGroup',
|
'groupClass' => 'app\models\SupplyGroup',
|
||||||
'productClass' => 'app\models\Supply',
|
'productClass' => 'app\models\Supply',
|
||||||
'offerClass' => 'app\models\Product',
|
'offerClass' => 'app\models\SupplyEdgeProduct',
|
||||||
'partnerClass' => 'app\models\Account',
|
'partnerClass' => 'app\models\Account',
|
||||||
'documentClass' => 'app\models\Purchase',
|
'documentClass' => 'app\models\Purchase',
|
||||||
'auth' => function ($mail, $pswd) {
|
'auth' => function ($mail, $pswd) {
|
||||||
// Необходимо уничтожить AccountForm
|
// Необходимо уничтожить AccountForm
|
||||||
return (new \app\models\AccountForm())->authentication($mail, $pswd);
|
// return (new \app\models\AccountForm())->authentication($mail, $pswd);
|
||||||
|
|
||||||
|
if ($user = \app\models\Account::findByMail($mail)) {
|
||||||
|
if ($user->validatePassword($pswd)) {
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
|
|
@ -17,7 +17,16 @@ class Account extends Document implements IdentityInterface, PartnerInterface
|
||||||
{
|
{
|
||||||
return array_merge(
|
return array_merge(
|
||||||
parent::attributes(),
|
parent::attributes(),
|
||||||
['mail', 'pswd', 'name', 'simc', 'sity', 'comp', 'taxn', 'auth']
|
[
|
||||||
|
'mail',
|
||||||
|
'pswd',
|
||||||
|
'name',
|
||||||
|
'simc',
|
||||||
|
'sity',
|
||||||
|
'comp',
|
||||||
|
'taxn',
|
||||||
|
'auth'
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,11 +82,16 @@ class Account extends Document implements IdentityInterface, PartnerInterface
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId()
|
public function getId(): string
|
||||||
{
|
{
|
||||||
return $this->_key;
|
return $this->_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function readId(): string
|
||||||
|
{
|
||||||
|
return self::collectionName() . '/' . $this->getId();
|
||||||
|
}
|
||||||
|
|
||||||
public function getAuthKey()
|
public function getAuthKey()
|
||||||
{
|
{
|
||||||
return $this->auth;
|
return $this->auth;
|
||||||
|
|
|
@ -2,30 +2,36 @@
|
||||||
|
|
||||||
namespace app\models;
|
namespace app\models;
|
||||||
|
|
||||||
|
use Yii;
|
||||||
use explosivebit\arangodb\ActiveRecord;
|
use explosivebit\arangodb\ActiveRecord;
|
||||||
|
|
||||||
abstract class Document extends ActiveRecord
|
abstract class Document extends ActiveRecord
|
||||||
{
|
{
|
||||||
public function attributes()
|
public function attributes()
|
||||||
{
|
|
||||||
return ['_key', 'date'];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function rules()
|
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
// [
|
'_key',
|
||||||
// 'date',
|
'date',
|
||||||
// 'required',
|
'writer'
|
||||||
// 'message' => 'Заполните поле: {attribute}'
|
|
||||||
// ]
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function attributeLabels()
|
public function attributeLabels()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'date' => 'Дата'
|
'date' => 'Дата',
|
||||||
|
'writer' => 'Аккаунт записавшего'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'writer',
|
||||||
|
'string'
|
||||||
|
// Надо добавить проверку существования аккаунта
|
||||||
|
]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,16 +39,23 @@ abstract class Document extends ActiveRecord
|
||||||
{
|
{
|
||||||
if (parent::beforeSave($data)) {
|
if (parent::beforeSave($data)) {
|
||||||
if ($this->isNewRecord) {
|
if ($this->isNewRecord) {
|
||||||
$this->date = time();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->date = time();
|
||||||
|
$this->writer = $this->writer ?? Yii::$app->user->identity->readId();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function readAmount()
|
public function readId(): ?string
|
||||||
|
{
|
||||||
|
return isset($this->_key) ? static::collectionName() . '/' . $this->_key : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function readAmount(): int
|
||||||
{
|
{
|
||||||
return static::find()->count();
|
return static::find()->count();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,53 +4,89 @@ namespace app\models;
|
||||||
|
|
||||||
use explosivebit\arangodb\ActiveRecord;
|
use explosivebit\arangodb\ActiveRecord;
|
||||||
|
|
||||||
abstract class Edge extends ActiveRecord
|
abstract class Edge extends Document
|
||||||
{
|
{
|
||||||
public function attributes()
|
public function attributes()
|
||||||
{
|
{
|
||||||
return ['_key', '_from', '_to', 'date', 'type', 'account'];
|
return array_merge(
|
||||||
}
|
parent::attributes(),
|
||||||
|
|
||||||
public function rules()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
[
|
[
|
||||||
['_from', '_to', 'date', 'type', 'account'],
|
'_from',
|
||||||
'required',
|
'_to',
|
||||||
'message' => 'Заполните поле: {attribute}'
|
'type'
|
||||||
],
|
|
||||||
[
|
|
||||||
'date',
|
|
||||||
'integer'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'type',
|
|
||||||
'string'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'account',
|
|
||||||
'string'
|
|
||||||
// Надо добавить проверку существования аккаунта
|
|
||||||
]
|
]
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function attributeLabels()
|
public function attributeLabels()
|
||||||
{
|
{
|
||||||
return [
|
return array_merge(
|
||||||
'date' => 'Дата',
|
parent::attributeLabels(),
|
||||||
'type' => 'Тип',
|
[
|
||||||
'account' => 'Аккаунт'
|
'date' => 'От кого',
|
||||||
];
|
'date' => 'К кому',
|
||||||
|
'type' => 'Тип'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return array_merge(
|
||||||
|
parent::rules(),
|
||||||
|
[
|
||||||
|
[
|
||||||
|
['_from', '_to'],
|
||||||
|
'required',
|
||||||
|
'message' => 'Заполните поле: {attribute}'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'type',
|
||||||
|
'string'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Записать
|
||||||
|
*/
|
||||||
|
public function write(string $_from, string $_to, string $type = '', array $data = []): ?static
|
||||||
|
{
|
||||||
|
// Инициализация
|
||||||
|
$edge = isset($this->_key) ? $this : new static;
|
||||||
|
|
||||||
|
// Настройка
|
||||||
|
$edge->_from = $_from;
|
||||||
|
$edge->_to = $_to;
|
||||||
|
$edge->type = $type;
|
||||||
|
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
if(is_int($key)) {
|
||||||
|
// Если ключ задан автоматически
|
||||||
|
|
||||||
|
$edge->{$value} = true;
|
||||||
|
} else {
|
||||||
|
// Иначе ключ записан вручную
|
||||||
|
|
||||||
|
$edge->{$key} = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запись
|
||||||
|
$edge->save();
|
||||||
|
|
||||||
|
return $edge;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function beforeSave($data)
|
public function beforeSave($data)
|
||||||
{
|
{
|
||||||
if (parent::beforeSave($data)) {
|
if (parent::beforeSave($data)) {
|
||||||
if ($this->isNewRecord) {
|
if ($this->isNewRecord) {
|
||||||
$this->date = time();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->type = $this->type ?? '';
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,30 +3,37 @@
|
||||||
namespace app\models;
|
namespace app\models;
|
||||||
|
|
||||||
use moonland\phpexcel\Excel;
|
use moonland\phpexcel\Excel;
|
||||||
use carono\exchange1c\interfaces\ProductInterface;
|
|
||||||
use Zenwalker\CommerceML\Model\Product as Product1c;
|
|
||||||
|
|
||||||
class Product extends Document implements ProductInterface
|
class Product extends Document
|
||||||
{
|
{
|
||||||
const SCENARIO_IMPORT = 'import';
|
const SCENARIO_IMPORT = 'import';
|
||||||
|
const SCENARIO_WRITE = 'write';
|
||||||
|
|
||||||
public $file;
|
public $file;
|
||||||
public $group;
|
public $group;
|
||||||
|
|
||||||
public static function collectionName()
|
public static function collectionName(): string
|
||||||
{
|
{
|
||||||
return 'product';
|
return 'product';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function attributes()
|
public function attributes(): array
|
||||||
{
|
{
|
||||||
return array_merge(
|
return array_merge(
|
||||||
parent::attributes(),
|
parent::attributes(),
|
||||||
['name', 'catn', 'oemn', 'data', 'cost', 'time']
|
[
|
||||||
|
'name',
|
||||||
|
'ocid',
|
||||||
|
'catn',
|
||||||
|
'oemn'
|
||||||
|
// 'data',
|
||||||
|
// 'cost',
|
||||||
|
// 'time'
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function rules()
|
public function rules(): array
|
||||||
{
|
{
|
||||||
return array_merge(
|
return array_merge(
|
||||||
parent::rules(),
|
parent::rules(),
|
||||||
|
@ -35,6 +42,7 @@ class Product extends Document implements ProductInterface
|
||||||
['name', 'catn'],
|
['name', 'catn'],
|
||||||
'required',
|
'required',
|
||||||
'message' => 'Заполните поля: {attribute}',
|
'message' => 'Заполните поля: {attribute}',
|
||||||
|
'on' => self::SCENARIO_WRITE,
|
||||||
'except' => self::SCENARIO_IMPORT
|
'except' => self::SCENARIO_IMPORT
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
@ -43,7 +51,7 @@ class Product extends Document implements ProductInterface
|
||||||
'message' => 'Заполните поля: {attribute}',
|
'message' => 'Заполните поля: {attribute}',
|
||||||
'on' => self::SCENARIO_IMPORT
|
'on' => self::SCENARIO_IMPORT
|
||||||
],
|
],
|
||||||
['catn', 'integer', 'message' => '{attribute} должен быть числом'],
|
['catn', 'string', 'message' => '{attribute} должен быть строкой'],
|
||||||
// ['oemn', 'integer'], Нужна своя проверка на массив
|
// ['oemn', 'integer'], Нужна своя проверка на массив
|
||||||
[
|
[
|
||||||
'file',
|
'file',
|
||||||
|
@ -61,37 +69,24 @@ class Product extends Document implements ProductInterface
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function attributeLabels()
|
public function attributeLabels(): array
|
||||||
{
|
{
|
||||||
return array_merge(
|
return array_merge(
|
||||||
parent::attributeLabels(),
|
parent::attributeLabels(),
|
||||||
[
|
[
|
||||||
'name' => 'Название (name)',
|
'name' => 'Название (name)',
|
||||||
|
'ocid' => 'Идентификатор 1C (ocid)',
|
||||||
'catn' => 'Каталожный номер (catn)',
|
'catn' => 'Каталожный номер (catn)',
|
||||||
'oemn' => 'OEM номера (oemn)',
|
'oemn' => 'OEM номера (oemn)',
|
||||||
'data' => 'Данные товара (data)',
|
// 'data' => 'Данные товара (data)',
|
||||||
'cost' => 'Цены (cost)',
|
// 'cost' => 'Цены (cost)',
|
||||||
'time' => 'Сроки доставки (time)',
|
// 'time' => 'Сроки доставки (time)',
|
||||||
'file' => 'Документ',
|
'file' => 'Документ',
|
||||||
'group' => 'Группа',
|
'group' => 'Группа'
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function beforeSave($data)
|
|
||||||
{
|
|
||||||
if (parent::beforeSave($data)) {
|
|
||||||
if ($this->isNewRecord) {
|
|
||||||
// Надо избавиться от unset();
|
|
||||||
unset($this->_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function import()
|
public function import()
|
||||||
{
|
{
|
||||||
// Инициализация массива данных
|
// Инициализация массива данных
|
||||||
|
@ -144,171 +139,6 @@ class Product extends Document implements ProductInterface
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Установка реквизитов для продукта
|
|
||||||
*/
|
|
||||||
// public function setRequisite1c(string $name, string $value): bool
|
|
||||||
public function setRequisite1c($name, $value): bool
|
|
||||||
{
|
|
||||||
if (!$requisite = Requisite::readByName($name)) {
|
|
||||||
// Реквизиты не найдены
|
|
||||||
|
|
||||||
// Инициализация
|
|
||||||
$requisite = new Requisite();
|
|
||||||
|
|
||||||
$requisite->name = $name;
|
|
||||||
$requisite->value = $value;
|
|
||||||
|
|
||||||
// Запись
|
|
||||||
return $requisite->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Установка группы, где находится продукт
|
|
||||||
*/
|
|
||||||
// public function setGroup1c(ProductGroup $group): bool
|
|
||||||
public function setGroup1c($group): bool
|
|
||||||
{
|
|
||||||
// Чтение группы
|
|
||||||
$group = SupplyGroup::readByOnecName($group->id)[0];
|
|
||||||
|
|
||||||
// Запись ребра: ПОСТАВКА => ГРУППА ПОСТАВОК
|
|
||||||
return static::writeEdgeBetweenGroup(static::collectionName() . '/' . $this->_key, $group->collectionName() . '/' . $group->_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Запись всех параметров. Вызывается 1 раз при импорте
|
|
||||||
*/
|
|
||||||
public static function createProperties1c($properties): void
|
|
||||||
{
|
|
||||||
// Это нам не нужно, кажется, надо будет тестить
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Zenwalker\CommerceML\Model\Property $property
|
|
||||||
*/
|
|
||||||
// foreach ($properties as $property) {
|
|
||||||
// $propertyModel = Property::createByMl($property);
|
|
||||||
// foreach ($property->getAvailableValues() as $value) {
|
|
||||||
// if (!$propertyValue = PropertyValue::findOne(['onec_name' => $value->id])) {
|
|
||||||
// $propertyValue = new PropertyValue();
|
|
||||||
// $propertyValue->name = (string)$value->Значение;
|
|
||||||
// $propertyValue->property_id = $propertyModel->id;
|
|
||||||
// $propertyValue->onec_name = (string)$value->ИдЗначения;
|
|
||||||
// $propertyValue->save();
|
|
||||||
// unset($propertyValue);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* $property - Свойство товара (import.xml > Классификатор > Свойства > Свойство)
|
|
||||||
* $property->value - Разыменованное значение (string) (import.xml > Классификатор > Свойства > Свойство > Значение)
|
|
||||||
* $property->getValueModel() - Данные по значению, Ид значения, и т.д (import.xml > Классификатор > Свойства > Свойство > ВариантыЗначений > Справочник)
|
|
||||||
*
|
|
||||||
* @param MlProperty $property
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function setProperty1c($property): void
|
|
||||||
{
|
|
||||||
// Это тоже нам не нужно
|
|
||||||
|
|
||||||
// $propertyModel = Property::findOne(['onec_name' => $property->id]);
|
|
||||||
// $propertyValue = $property->getValueModel();
|
|
||||||
// if ($propertyAccountingId = (string)$propertyValue->ИдЗначения) {
|
|
||||||
// $value = PropertyValue::findOne(['onec_name' => $propertyAccountingId]);
|
|
||||||
// $attributes = ['property_value_id' => $value->id];
|
|
||||||
// } else {
|
|
||||||
// $attributes = ['value' => $propertyValue->value];
|
|
||||||
// }
|
|
||||||
// $this->addPivot($propertyModel, PvProductProperty::class, $attributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* В этой фукнции мы получаем абсолютный путь до картинки и название изрбражения (для alt аттрибута)
|
|
||||||
*
|
|
||||||
* @param string $path
|
|
||||||
* @param string $caption
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function addImage1c($path, $caption): bool
|
|
||||||
{
|
|
||||||
// if (!$this->getImages()->andWhere(['md5' => md5_file($path)])->exists()) {
|
|
||||||
// $this->addPivot(FileUpload::startUpload($path)->process(), PvProductImage::class, ['caption' => $caption]);
|
|
||||||
// }
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* В эту фукнцию отправляется xml данные предложения из файла
|
|
||||||
*/
|
|
||||||
// public function getOffer1c(Supply $offer): Supply
|
|
||||||
public function getOffer1c($offer): Supply
|
|
||||||
{
|
|
||||||
$supply = Supply::createByMl($offer);
|
|
||||||
$supply->product_id = $this->id;
|
|
||||||
if ($supply->getDirtyAttributes()) {
|
|
||||||
$supply->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $supply;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param MlOffer $offer
|
|
||||||
*/
|
|
||||||
public static function createByMl($offer): Supply
|
|
||||||
{
|
|
||||||
if (!$model = static::readByOnecName($offer->id)) {
|
|
||||||
// Нет записей в базе данных
|
|
||||||
|
|
||||||
// Инициализация
|
|
||||||
$model = new static;
|
|
||||||
|
|
||||||
$model->name = (string) $offer->name;
|
|
||||||
$model->onec_name = (string) $offer->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
$model->remnant = (string) $offer->Количество;
|
|
||||||
|
|
||||||
return $model;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $product
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
public static function createModel1c($product): static
|
|
||||||
{
|
|
||||||
if (!$model = static::findOne(['onec_name' => $product->id])) {
|
|
||||||
$model = new static();
|
|
||||||
$model->onec_name = $product->id;
|
|
||||||
}
|
|
||||||
$model->name = $product->name;
|
|
||||||
$model->description = (string) $product->Описание;
|
|
||||||
$model->article = (string) $product->Артикул;
|
|
||||||
|
|
||||||
$model->save();
|
|
||||||
|
|
||||||
return $model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setRaw1cData($cml, $object)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Название поля в котором хранится ID из 1C
|
|
||||||
*/
|
|
||||||
public static function getIdFieldName1c(): string
|
|
||||||
{
|
|
||||||
return 'onec_name';
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function writeEdgeBetweenGroup(string $from, string $to): bool
|
private static function writeEdgeBetweenGroup(string $from, string $to): bool
|
||||||
{
|
{
|
||||||
// Инициализация
|
// Инициализация
|
||||||
|
@ -337,16 +167,14 @@ class Product extends Document implements ProductInterface
|
||||||
|
|
||||||
public static function readById(string $_key): ?Product
|
public static function readById(string $_key): ?Product
|
||||||
{
|
{
|
||||||
return Product::findOne(['_key' => $_key]);
|
return self::findOne(['_key' => $_key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getGroup1c(): ProductGroup
|
/**
|
||||||
|
* Поиск по каталожному номеру
|
||||||
|
*/
|
||||||
|
public static function readByCatn(string $catn): ?Product
|
||||||
{
|
{
|
||||||
return $this->group;
|
return self::findOne(['catn' => $catn]);
|
||||||
}
|
|
||||||
|
|
||||||
public static function readByOnecName(string $name): ?Product
|
|
||||||
{
|
|
||||||
return static::findOne([static::getIdFieldName1c() => $name]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ class ProductGroup extends Document implements GroupInterface
|
||||||
{
|
{
|
||||||
return array_merge(
|
return array_merge(
|
||||||
parent::attributes(),
|
parent::attributes(),
|
||||||
['name', 'onec_name', 'onec_prnt_name']
|
['name', 'onec_id', 'onec_prnt_id']
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,8 +40,8 @@ class ProductGroup extends Document implements GroupInterface
|
||||||
parent::attributeLabels(),
|
parent::attributeLabels(),
|
||||||
[
|
[
|
||||||
'name' => 'Название (name)',
|
'name' => 'Название (name)',
|
||||||
'onec_name' => 'Название 1C (onec_name)',
|
'onec_id' => 'Название 1C (onec_id)',
|
||||||
'onec_prnt_name' => 'Название родителя 1C (onec_prnt_name)',
|
'onec_prnt_id' => 'Название родителя 1C (onec_prnt_id)',
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -95,13 +95,13 @@ class ProductGroup extends Document implements GroupInterface
|
||||||
*/
|
*/
|
||||||
public static function createByML(Group $group): static|array|null
|
public static function createByML(Group $group): static|array|null
|
||||||
{
|
{
|
||||||
if (!$model = static::readByOnecName($group->id)) {
|
if (!$model = static::readByOnecId($group->id)) {
|
||||||
// Группа не найдена
|
// Группа не найдена
|
||||||
|
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$model = new static;
|
$model = new static;
|
||||||
|
|
||||||
$model->onec_name = $group->id;
|
$model->onec_id = $group->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
$model->name = $group->name;
|
$model->name = $group->name;
|
||||||
|
@ -112,11 +112,11 @@ class ProductGroup extends Document implements GroupInterface
|
||||||
// Инициализация (рекурсия)
|
// Инициализация (рекурсия)
|
||||||
$parentModel = static::createByML($parent);
|
$parentModel = static::createByML($parent);
|
||||||
|
|
||||||
$model->onec_prnt_name = $parentModel->id;
|
$model->onec_prnt_id = $parentModel->id;
|
||||||
|
|
||||||
unset($parentModel);
|
unset($parentModel);
|
||||||
} else {
|
} else {
|
||||||
$model->onec_prnt_name = null;
|
$model->onec_prnt_id = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$model->save();
|
$model->save();
|
||||||
|
@ -165,11 +165,11 @@ class ProductGroup extends Document implements GroupInterface
|
||||||
*/
|
*/
|
||||||
public static function getIdFieldName1c(): string
|
public static function getIdFieldName1c(): string
|
||||||
{
|
{
|
||||||
return 'onec_name';
|
return 'onec_id';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function readByOnecName(string $name): ?Product
|
public static function readByOnecId(string $onec_id): ?ProductGroup
|
||||||
{
|
{
|
||||||
return static::findOne([static::getIdFieldName1c() => $name]);
|
return static::findOne(['onec_id' => $onec_id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,15 +6,15 @@ use carono\exchange1c\interfaces\DocumentInterface;
|
||||||
|
|
||||||
class Purchase extends Document implements DocumentInterface
|
class Purchase extends Document implements DocumentInterface
|
||||||
{
|
{
|
||||||
public static function collectionName()
|
public static function collectionName(): string
|
||||||
{
|
{
|
||||||
return 'requisite';
|
return 'purchase';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return DocumentInterface[]
|
* @return DocumentInterface[]
|
||||||
*/
|
*/
|
||||||
public static function findDocuments1c()
|
public static function findDocuments1c(): ?self
|
||||||
{
|
{
|
||||||
return self::find()->andWhere(['status_id' => 2])->all();
|
return self::find()->andWhere(['status_id' => 2])->all();
|
||||||
}
|
}
|
||||||
|
@ -22,13 +22,14 @@ class Purchase extends Document implements DocumentInterface
|
||||||
/**
|
/**
|
||||||
* @return OfferInterface[]
|
* @return OfferInterface[]
|
||||||
*/
|
*/
|
||||||
public function getOffers1c()
|
public function getOffers1c(): mixed
|
||||||
{
|
{
|
||||||
return $this->offers;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRequisites1c()
|
public function getRequisites1c(): mixed
|
||||||
{
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,32 +37,15 @@ class Purchase extends Document implements DocumentInterface
|
||||||
*
|
*
|
||||||
* @return PartnerInterface
|
* @return PartnerInterface
|
||||||
*/
|
*/
|
||||||
public function getPartner1c()
|
public function getPartner1c(): Account
|
||||||
{
|
{
|
||||||
return $this->user;
|
// !!!!!!!!!!!!!!!!!!!
|
||||||
|
return $this->user ?? new Account;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getExportFields1c($context = null)
|
public function getExportFields1c($context = null)
|
||||||
{
|
{
|
||||||
return [
|
return [];
|
||||||
'Ид' => 'id',
|
|
||||||
'Наименование' => 'login',
|
|
||||||
'ПолноеНаименование' => 'full_name',
|
|
||||||
'Фамилия' => 'surname',
|
|
||||||
'Имя' => 'name',
|
|
||||||
'Контакты' => [
|
|
||||||
[
|
|
||||||
'@name' => 'Контакт',
|
|
||||||
'Тип' => 'Почта',
|
|
||||||
'Значение' => $this->email,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'@name' => 'Контакт',
|
|
||||||
'Тип' => 'ТелефонРабочий',
|
|
||||||
'Значение' => $this->phone,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -71,10 +55,10 @@ class Purchase extends Document implements DocumentInterface
|
||||||
*/
|
*/
|
||||||
public static function getIdFieldName1c()
|
public static function getIdFieldName1c()
|
||||||
{
|
{
|
||||||
return 'accounting_id';
|
return 'onec["Ид"]';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setRaw1cData($cml, $object)
|
public function setRaw1cData($cml, $object): void
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,153 +6,182 @@ use Yii;
|
||||||
use app\models\Account;
|
use app\models\Account;
|
||||||
use app\models\Product;
|
use app\models\Product;
|
||||||
use app\models\SupplyEdgeProduct;
|
use app\models\SupplyEdgeProduct;
|
||||||
use carono\exchange1c\interfaces\OfferInterface;
|
use app\models\traits\Xml2Array;
|
||||||
|
use carono\exchange1c\interfaces\ProductInterface;
|
||||||
|
|
||||||
class Supply extends Product implements OfferInterface
|
// class Supply extends Product implements OfferInterface
|
||||||
|
class Supply extends Product implements ProductInterface
|
||||||
{
|
{
|
||||||
public static function collectionName()
|
use Xml2Array;
|
||||||
|
|
||||||
|
public static function collectionName(): string
|
||||||
{
|
{
|
||||||
return 'supply';
|
return 'supply';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function afterSave($data, $vars)
|
public function attributes(): array
|
||||||
{
|
{
|
||||||
if (is_null($product = self::readByCatn($this->catn))) {
|
return array_merge(
|
||||||
// Товар не найден
|
parent::attributes(),
|
||||||
|
[
|
||||||
|
'onec'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attributeLabels(): array
|
||||||
|
{
|
||||||
|
return array_merge(
|
||||||
|
parent::attributeLabels(),
|
||||||
|
[
|
||||||
|
'onec' => 'Данные 1C'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function afterSave($data, $vars): void
|
||||||
|
{
|
||||||
|
// Запись ребра: АККАУНТ -> ПОСТАВКА
|
||||||
|
(new AccountEdgeSupply)->write(Yii::$app->user->identity->readId(), $this->readId(), 'import');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRequisite1c($name, $value): mixed
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Установка группы, где находится продукт
|
||||||
|
*/
|
||||||
|
public function setGroup1c($group): mixed
|
||||||
|
{
|
||||||
|
// Чтение группы
|
||||||
|
// if ($group = SupplyGroup::readByOnecId($group->id)) {
|
||||||
|
// // Запись ребра: ПОСТАВКА => ГРУППА ПОСТАВОК
|
||||||
|
// return static::writeEdgeBetweenGroup(static::collectionName() . '/' . $this->_key, $group->collectionName() . '/' . $group->_key);
|
||||||
|
// }
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function createProperties1c($properties): mixed
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setProperty1c($property): mixed
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addImage1c($path, $caption): mixed
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запись ребра (предложения от поставки к продукту)
|
||||||
|
*/
|
||||||
|
public function getOffer1c($offer): SupplyEdgeProduct
|
||||||
|
{
|
||||||
|
if (empty($this->catn)) {
|
||||||
|
// Не передан каталожный номер
|
||||||
|
|
||||||
|
// Разработчику библеотеки надо дать по жопе
|
||||||
|
return new SupplyEdgeProduct;
|
||||||
|
} else if (!$catn = Product::readByCatn($this->catn)) {
|
||||||
|
// Продукт не найден
|
||||||
|
|
||||||
|
if (!$this->initProduct()) {
|
||||||
|
// Не удалось инициализировать продукт
|
||||||
|
|
||||||
|
// Разработчику библеотеки надо дать по жопе
|
||||||
|
return new SupplyEdgeProduct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$catn = Product::readByCatn($this->catn);
|
||||||
|
|
||||||
|
// Запись ребра: ПОСТАВКА -> ПРОДУКТ
|
||||||
|
return (new SupplyEdgeProduct)->write(
|
||||||
|
$this->readId(),
|
||||||
|
$catn->readId(),
|
||||||
|
'sell',
|
||||||
|
[
|
||||||
|
'onec' => self::xml2array($offer->xml)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Создать продукт
|
||||||
|
*/
|
||||||
|
public static function createModel1c($product): self
|
||||||
|
{
|
||||||
// Инициализация
|
// Инициализация
|
||||||
$product = (new Product(array_intersect_key($this->getAttributes(), (new Product)->getAttributes())));
|
$model = self::readByOnecId($id = (string) $product->Ид) ?? new self;
|
||||||
|
|
||||||
|
// Настройки
|
||||||
|
$model->ocid = $id ?? null;
|
||||||
|
$model->catn = (string) $product->Артикул;
|
||||||
|
$model->oemn = null;
|
||||||
|
$model->onec = self::xml2array($product->xml);
|
||||||
|
|
||||||
// Запись
|
// Запись
|
||||||
if (!$product->save()) {
|
$model->save();
|
||||||
return false;
|
|
||||||
}
|
return $model;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Запись рёбер: АККАУНТ => ПОСТАВКА => ТОВАР, и проверка на то, что оба созданы
|
protected function initProduct(): bool
|
||||||
static::writeEdgeBetweenAccount(Account::collectionName() . '/' . Yii::$app->user->identity->_key, static::collectionName() . '/' . $this->_key);
|
|
||||||
static::writeEdgeBetweenProduct(static::collectionName() . '/' . $this->_key, Product::collectionName() . '/' . $product->_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* В этом методе необходимо создать все типы цен, фукнция вызывается один раз
|
|
||||||
*/
|
|
||||||
public static function createPriceTypes1c($types): void
|
|
||||||
{
|
{
|
||||||
foreach ($types as $type) {
|
// Надо не забыть сделать выборку полей и ручное подключение
|
||||||
// PriceType::createByMl($type);
|
|
||||||
}
|
if (empty($this->catn)) {
|
||||||
|
// Не передан каталожный номер
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} else if (Product::readByCatn($this->catn)) {
|
||||||
|
// Продукт уже был инициализирован
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// Инициализация
|
||||||
* offers.xml > ПакетПредложений > Предложения > Предложение > Цены
|
$product = new Product();
|
||||||
*
|
|
||||||
* Цена товара,
|
// Настройки
|
||||||
* К $price можно обратиться как к массиву, чтобы получить список цен (Цены > Цена)
|
$product->catn = $this->catn;
|
||||||
* $price->type - тип цены (offers.xml > ПакетПредложений > ТипыЦен > ТипЦены)
|
|
||||||
*
|
// Запись
|
||||||
* @param \Zenwalker\CommerceML\Model\Price $price
|
return $product->save();
|
||||||
*/
|
}
|
||||||
|
|
||||||
|
|
||||||
public function setPrice1c($price): void
|
public function setPrice1c($price): void
|
||||||
{
|
{
|
||||||
// $priceType = PriceType::findOne(['accounting_id' => $price->getType()->id]);
|
}
|
||||||
// $priceModel = Price::createByMl($price, $this, $priceType);
|
|
||||||
// $this->addPivot($priceModel, PvOfferPrice::class);
|
public function setRaw1cData($cml, $object): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function readByOnecId(string $ocid): ?Supply
|
||||||
|
{
|
||||||
|
return self::findOne([self::getIdFieldName1c() => $ocid]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGroup1c(): SupplyGroup
|
||||||
|
{
|
||||||
|
return $this->group;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* offers.xml > ПакетПредложений > Предложения > Предложение > ХарактеристикиТовара > ХарактеристикаТовара
|
* Название поля в котором хранится ID из 1C
|
||||||
*
|
|
||||||
* Характеристики товара
|
|
||||||
* $name - Наименование
|
|
||||||
* $value - Значение
|
|
||||||
*
|
|
||||||
* @param \Zenwalker\CommerceML\Model\Simple $specification
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function setSpecification1c($specification)
|
public static function getIdFieldName1c(): string
|
||||||
{
|
{
|
||||||
// $specificationModel = Specification::createByMl($specification);
|
return 'ocid';
|
||||||
// $this->addPivot($specificationModel, PvOfferSpecification::class, ['value' => (string)$specification->Значение]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getExportFields1c($context = null)
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'Ид' => 'id',
|
|
||||||
'Наименование' => 'login',
|
|
||||||
'ПолноеНаименование' => 'full_name',
|
|
||||||
'Фамилия' => 'surname',
|
|
||||||
'Имя' => 'name',
|
|
||||||
'Контакты' => [
|
|
||||||
[
|
|
||||||
'@name' => 'Контакт',
|
|
||||||
'Тип' => 'Почта',
|
|
||||||
'Значение' => $this->email,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'@name' => 'Контакт',
|
|
||||||
'Тип' => 'ТелефонРабочий',
|
|
||||||
'Значение' => $this->phone,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function writeEdgeBetweenAccount(string $from, string $to): bool
|
|
||||||
{
|
|
||||||
// Инициализация
|
|
||||||
$edge = new AccountEdgeSupply();
|
|
||||||
|
|
||||||
// Настройка
|
|
||||||
$edge->_from = $from;
|
|
||||||
$edge->_to = $to;
|
|
||||||
|
|
||||||
// Запись
|
|
||||||
return $edge->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function writeEdgeBetweenProduct(string $from, string $to): bool
|
|
||||||
{
|
|
||||||
// Инициализация
|
|
||||||
$edge = new SupplyEdgeProduct();
|
|
||||||
|
|
||||||
// Настройка
|
|
||||||
$edge->_from = $from;
|
|
||||||
$edge->_to = $to;
|
|
||||||
|
|
||||||
// Запись
|
|
||||||
return $edge->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
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 readByCatn(string $catn): ?Product
|
|
||||||
{
|
|
||||||
return Product::findOne(['catn' => $catn]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,76 @@
|
||||||
|
|
||||||
namespace app\models;
|
namespace app\models;
|
||||||
|
|
||||||
class SupplyEdgeProduct extends Edge
|
use app\models\traits\Xml2Array;
|
||||||
|
use carono\exchange1c\interfaces\OfferInterface;
|
||||||
|
use Zenwalker\CommerceML\Model\Offer;
|
||||||
|
|
||||||
|
class SupplyEdgeProduct extends Edge implements OfferInterface
|
||||||
{
|
{
|
||||||
public static function collectionName()
|
use Xml2Array;
|
||||||
|
|
||||||
|
public static function collectionName(): string
|
||||||
{
|
{
|
||||||
return 'supply_edge_product';
|
return 'supply_edge_product';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function attributes(): array
|
||||||
|
{
|
||||||
|
return array_merge(
|
||||||
|
parent::attributes(),
|
||||||
|
[
|
||||||
|
'ocid',
|
||||||
|
'onec'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attributeLabels(): array
|
||||||
|
{
|
||||||
|
return array_merge(
|
||||||
|
parent::attributeLabels(),
|
||||||
|
[
|
||||||
|
'ocid' => 'Идентификатор 1C (ocid)',
|
||||||
|
'onec' => 'Данные 1C'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function createPriceTypes1c($types): mixed
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPrice1c($price): mixed
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSpecification1c($specification): mixed
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getExportFields1c($context = null): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGroup1c(): ProductGroup
|
||||||
|
{
|
||||||
|
return $this->group ?? new ProductGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function readByOnecId(string $ocid): ?Supply
|
||||||
|
{
|
||||||
|
return self::findOne([self::getIdFieldName1c() => $ocid]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Название поля в котором хранится ID из 1C
|
||||||
|
*/
|
||||||
|
public static function getIdFieldName1c(): string
|
||||||
|
{
|
||||||
|
return 'ocid';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,9 +34,4 @@ class SupplyGroup extends ProductGroup
|
||||||
// Запись
|
// Запись
|
||||||
return $edge->save();
|
return $edge->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function readByOnecName(string $onec_name): ?Product
|
|
||||||
{
|
|
||||||
return static::findOne(['onec_name' => $onec_name]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\models\traits;
|
||||||
|
|
||||||
|
trait Xml2Array {
|
||||||
|
protected static function xml2array($xmlObject, $out = [])
|
||||||
|
{
|
||||||
|
foreach ((array) $xmlObject as $index => $node)
|
||||||
|
$out[$index] = (is_object($node) || is_array($node)) ? self::xml2array($node) : $node;
|
||||||
|
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue