Исправления

This commit is contained in:
Arsen Mirzaev Tatyano-Muradovich 2021-04-12 05:32:13 +10:00
parent a11a5da2e1
commit fe0453f91b
2 changed files with 389 additions and 455 deletions

View File

@ -6,42 +6,34 @@ namespace app\models;
use yii; use yii;
use app\models\Account; use app\models\traits\SearchByEdge;
use app\models\Product;
use app\models\SupplyEdgeProduct;
use app\models\traits\Xml2Array;
use carono\exchange1c\interfaces\OfferInterface;
use carono\exchange1c\interfaces\ProductInterface;
use carono\exchange1c\controllers\ApiController; use carono\exchange1c\controllers\ApiController;
use carono\exchange1c\interfaces\DocumentInterface;
use exception; use Exception;
/** /**
* Поставка (выгрузка товаров от поставщиков) * Заказ
* *
* Представляет собой предложения от поставщиков которые добавляются * @see Account Заказчик
* в универсальные лоты товаров в асспортименте магазина * @see Supply Поставки для заказа
*
* @see Product Продукт (туда добавляются поставки)
*/ */
class Supply extends Product implements ProductInterface, OfferInterface class Order extends Document implements DocumentInterface
{ {
use Xml2Array; use SearchByEdge;
/** /**
* Количество * Поставки для записи
*
* Используется при выводе в корзине
*/ */
public int $amnt = 0; public array $supplies;
/** /**
* Имя коллекции * Имя коллекции
*/ */
public static function collectionName(): string public static function collectionName(): string
{ {
return 'supply'; return 'order';
} }
/** /**
@ -52,10 +44,8 @@ class Supply extends Product implements ProductInterface, OfferInterface
return array_merge( return array_merge(
parent::attributes(), parent::attributes(),
[ [
'cost', 'ocid',
'onec', 'sync'
'oemn',
'ocid'
] ]
); );
} }
@ -68,10 +58,8 @@ class Supply extends Product implements ProductInterface, OfferInterface
return array_merge( return array_merge(
parent::attributeLabels(), parent::attributeLabels(),
[ [
'cost' => 'Стоимость (cost)', 'ocid' => 'Идентификатор 1C',
'onec' => 'Данные 1С', 'sync' => 'Статус синхронизации с 1C'
'oemn' => 'OEM-номера',
'ocid' => 'Идентификатор 1C (ocid)'
] ]
); );
} }
@ -84,492 +72,443 @@ class Supply extends Product implements ProductInterface, OfferInterface
return array_merge( return array_merge(
parent::rules(), parent::rules(),
[ [
// [ [
// [ 'sync',
// 'oemn' 'boolean',
// ], 'message' => '{attribute} должен иметь логическое значение'
// 'arrayValidator', ],
// 'message' => '{attribute} должен быть массивом.' [
// ] 'sync',
'default',
'value' => false
]
] ]
); );
} }
/** /**
* После сохранения * Подключение к аккаунту
*/ */
public function afterSave($data, $vars): void public function connect(Account $account): ?AccountEdgeOrder
{ {
if (AccountEdgeSupply::searchByVertex(yii::$app->user->id, $this->readId())) { // Запись ребра: АККАУНТ -> ЗАКАЗ
// Ребро: "АККАУНТ -> ПОСТАВКА" уже существует return AccountEdgeOrder::write($account->id, $this->readId(), 'current') ?? throw new Exception('Не удалось инициализировать ребро: АККАУНТ -> ЗАКАЗ');
} else {
// Ребра не существует
// Запись ребра: АККАУНТ -> ПОСТАВКА
(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
{
// Чтение группы
// if ($group = SupplyGroup::readByOcid($group->id)) {
// // Запись ребра: ПОСТАВКА => ГРУППА ПОСТАВОК
// return static::writeEdgeBetweenGroup(static::collectionName() . '/' . $this->_key, $group->collectionName() . '/' . $group->_key);
// }
return true;
}
/**
* Поиск через связь с аккаунтом
* *
* @param string|null $id Идентификатор пользователя * $supply = [ Supply $supply, int $amount = 1 ]
* @param string|array|null $select Запрашиваемые значения
*/
public static function searchByAccount(string|null $id = null, string|array|null $select = null, int|null $limit = 10): array
{
isset($id) ?: $id = yii::$app->user->id ?? throw new Exception('Не найден идентификатор');
return self::searchByEdge(
from: 'account',
to: 'supply',
subquery_where: [
[
'account._id' => $id
]
],
where: 'supply._id == account_edge_supply[0]._to AND supply.onec["ЗначенияСвойств"] != null',
select: $select,
limit: $limit
);
}
/**
* Запись данных свойств по UUID 1C
* *
* Ищет записанные свойства из 1C по их идентификатору и добавляет к ним * @param Supply|array $supply Поставка
* недостающие данные. Это костыль оставшийся от реляционных баз данных * @param Account $trgt Заказчик
* *
* @todo Понять что может храниться внутри "$model->onec['ЗначенияСвойств']['ЗначенияСвойства']" и переписать * @return int Количество записанных поставок
*
* @todo Создать параметр разделителя для администрации
*/ */
public static function createProperties1c($properties, Account|null $account = null): void public function writeSupply(Supply|string|array $supply, Account $trgt = null): int
{ {
// Инициализация // Инициализация
$account ?? $account = yii::$app->user->identity; $trgt ?? $trgt = yii::$app->user ?? throw new Exception('Не удалось инициализировать заказчика');
$models = self::searchByAccount($account->readId());
$properties = self::xml2array($properties->xml);
$account->on(ApiController::EVENT_AFTER_OFFER_SYNC, self::afterImport1c()); if ($supply instanceof Supply) {
// Передана инстанция класса поставки или второй элемент массива не является числом
foreach ($models as $model) { // Унификация входных данных
// Перебор записей $supply = [$supply->catn => 1];
}
if (is_null($this->_key)) {
// Корзина не инициализирована
// Инициализация // Инициализация
$changes = false; if (!$this->save()) {
$transit = $model->onec; // Инициализация заказа не удалась
foreach ($model->onec['ЗначенияСвойств'] as $attribute_name => $attribute_value) { throw new Exception('Ошибка при записи заказа в базу данных');
// Перебор аттрибутов
foreach ($properties as $property) {
// Перебор свойств
if (is_array($attribute_value) && is_array($property) && $attribute_value['Ид'] === $property['Ид']) {
// Совпадение идентификаторов
// Объединение данных
$transit['ЗначенияСвойств'][$attribute_name] = array_merge($attribute_value, $property, $transit['ЗначенияСвойств'][$attribute_name]);
// Запись индикатора наличия изменений
$changes = true;
} else {
// Объединение данных
$transit['ЗначенияСвойств'][$attribute_name] = $property;
}
}
} }
if ($changes) { // Инициализация ребра: АККАУНТ -> ЗАКАЗ
// Если указано, что записаны изменения if (!AccountEdgeOrder::write($trgt->readId(), $this->readId(), 'create')) {
// Инициализация не удалась
// Настройка ($transit нужен из-за особенностей __set()) throw new Exception('Ошибка при записи ребра от аккаунта до заказа в базу данных');
$model->onec = $transit;
foreach ($model->onec['ЗначенияСвойств'] as $property) {
// Перебор всех свойств
if (is_array($property)) {
// if ($property['Ид'] === $account->opts['import_sections_oem']) {
// // Если идентификатор свойства совпадает с указанным в настройках свойства хранящего OEM номера
// Настройка
$model->catn = $property['Значение'];
// }
}
}
// Запись
$model->save();
} }
} }
// Инициализация
$amount = 0;
foreach (is_array($supply) ? $supply : [$supply => 1] as $supply_raw => $amount_raw) {
// Перебор поставок
for ($i = 0; $i < $amount_raw; $i++) {
// Создание рёбер соразмерно запросу (добавление нескольких продуктов в корзину)
// Запись ребра: ЗАКАЗ -> ПОСТАВКА
if (!$supply_model = Supply::searchByCatn($supply_raw) or !OrderEdgeSupply::write($this->readId(), $supply_model->readId(), 'write')) {
// Поставка не найдена или запись ребра не удалась
continue;
} else {
// Ребро создано (товар подключен к заказу)
// Постинкрементация счётчика добавленных товаров
$amount++;
// Запись в журнал
$this->journal('write', ['target' => $supply_model->readId()]);
}
}
}
if ($amount === 0) {
// Отправка уведомления
self::notification('Неудачная попытка добавить товар в корзину');
} else if ($amount === 1) {
// Отправка уведомления
self::notification('Товар ' . $supply_model->catn . ' добавлен в корзину');
} else {
// Отправка уведомления
self::notification('Добавлено ' . $amount . ' товаров в корзину');
}
return $amount;
} }
/** /**
* Запись параметров из 1С * Удаление поставки
*/
public function setProperty1c($property): mixed
{
return true;
}
/**
* Запись изображений из 1С
* *
* @todo Добавить параметры в админ-панель * @param Supply|string|array $supply Товары
* Запретить доступ к изображениям *
* @return int Количество удалённых рёбер
*/ */
public function addImage1c($path, $caption): bool public function deleteSupply(Supply|string|array $supply): int
{ {
// Инициализация // Инициализация
$i = 0; $amount = 0;
if (!file_exists(YII_PATH_PUBLIC . $catalog = '/img/supplies/' . $this->_key)) { if ($supply instanceof Supply) {
// Директория для изображений продукта не найдена // Передана инстанция класса поставки или второй элемент массива не является числом
if (!mkdir(YII_PATH_PUBLIC . $catalog, 0775, true)) { // Унификация входных данных
// не удалось записать директорию $supply = [$supply->catn => 1];
return false;
};
} }
foreach ($this->imgs ?? [] as $image) { foreach (is_array($supply) ? $supply : [$supply => 1] as $catn => $amount_raw) {
// Перебор имеющихся изображений // Перебор товаров
if ($path === $image['sorc']) { if ($supply = Supply::searchByCatn($catn)) {
// Изображение уже записано на сервер foreach (OrderEdgeSupply::searchByVertex($this->readId(), $supply->readId(), limit: $amount_raw) as $edge) {
// Перебор рёбер до продукта (если товаров в заказе несколько)
return true; // Удаление
$edge->delete();
// Запись в журнал
$this->journal('delete', ['target' => $supply->readId()]);
// Постинкрементация счётчика удалённых рёбер
$amount++;
}
} }
} }
if ($amount === 0) {
// Отправка уведомления
self::notification('Неудачная попытка удалить товар из корзины');
} else if ($amount === 1) {
// Отправка уведомления
self::notification('Товар ' . $supply->catn . ' удалён из корзины');
} else {
// Отправка уведомления
self::notification('Удалено ' . $amount . ' товаров из корзины');
}
return $amount;
}
/**
* Поиск заказа
*/
public static function search(Account $account = null, string $type = 'current', int $limit = 1, int $page = 1, string $select = null): self|array|null
{
// Инициализация // Инициализация
$urn = basename($path); $account or $account = yii::$app->user ?? throw new Exception('Не удалось инициализировать пользователя');
// Запись // Генерация сдвига по запрашиваемым данным (пагинация)
copy($path, $path_local = YII_PATH_PUBLIC . $catalog . '/' . $urn); $offset = $limit * ($page - 1);
// Запись свойства if (strcasecmp($type, 'all') !== 0) {
$this->imgs = array_merge( // Если не указан параметр поиска всех заказов
$this->imgs ?? [],
[ $where_type = [
'account_edge_order.type' => $type
];
} else {
$where_type = [];
}
$return = self::searchByEdge(
from: 'account',
to: 'order',
subquery_where: [
[ [
'dscr' => $caption, 'account._id' => $account->id
'path' => $path_local, ],
'sorc' => $path $where_type
] ],
] foreach: ['edge' => 'account_edge_order'],
where: 'edge._to == order._id',
limit: $limit,
offset: $offset,
sort: ['DESC'],
select: $select,
direction: 'INBOUND'
); );
// Отправка в базу данных return $limit === 1 ? $return[0] ?? null : $return;
return $this->update();
} }
/** /**
* Запись ребра (предложения от поставок к продуктам) из 1С * Поиск содержимого заказа
* *
* @todo Разобраться зачем нужно возвращать SupplyEdgeProduct * @todo В будущем возможно заказ не только поставок реализовать
* Вернуть создание карточек, но только по условиям (загрузка от админа, например)
*/ */
public function getOffer1c($offer): SupplyEdgeProduct public function content(int $limit = 1, int $page = 1): Supply|array|null
{ {
if (empty($this->catn)) { // Генерация сдвига по запрашиваемым данным (пагинация)
// Не передан каталожный номер $offset = $limit * ($page - 1);
// Разработчику библеотеки надо дать по жопе // Поиск рёбер: ЗАКАЗ -> ПОСТАВКА
return new SupplyEdgeProduct; $supplies = Supply::searchByEdge(
} from: 'order',
to: 'supply',
edge: 'order_edge_supply',
subquery_where: [
[
'order._id' => $this->readId()
]
],
foreach: ['edge' => 'order_edge_supply'],
where: 'edge._to == supply._id',
limit: $limit,
offset: $offset,
direction: 'INBOUND'
);
if ( // Инициализация реестра дубликатов
!yii::$app->user->isGuest $registry = [];
&& yii::$app->user->identity->agnt
&& (yii::$app->user->identity->type === 'administrator'
|| yii::$app->user->identity->type === 'moderator')
) {
// Пользователь аутентифицирован и авторизован
// Инициализация п̸̨͇͑͋͠р̷̬̂́̀̊о̸̜̯̹̅͒͘͝д̴̨̨̨̟̈́̆у̴̨̭̮̠́͋̈́к̴̭͊̋̎т̵̛̣͈̔̐͆а̵̨͖͑ // Подсчёт и перестройка массива для очистки от дубликатов
$product = self::initEmpty($this->catn); foreach ($supplies as $key => &$supply) {
// Перебор поставок
if (!is_array($product)) { if (in_array($supply->catn, $registry)) {
// Создался только один товар и вернулся в виде модели // Если данная поставка найдена в реестре
$product = [$product]; // Удаление
} unset($supplies[$key]);
if (is_array($this->oemn)) {
// Значение OEM было инициализировано
foreach ($this->oemn as $oem) {
// Перебор артикулов из массива ОЕМ-номеров
// Инициализация и запись
$product[] = self::initEmpty($oem);
}
}
foreach ($product as $product) {
// Перебор всех инициализированных продуктов
if ($this->catn !== $product->catn) {
// Каталожные номера не соответствуют друг другу
continue;
}
// Код ниже скорее всего устарел
if (SupplyEdgeProduct::searchByVertex($this->readId(), $product->readId())) {
// Ребро уже существует
continue;
}
// Запись ребра: ПОСТАВКА -> ПРОДУКТ
$return = (new SupplyEdgeProduct)->write(
$this->readId(),
$product->readId(),
'connect',
[
'onec' => self::xml2array($offer->xml)
]
);
}
}
// Возвращает последнее сохранённое ребро
// Надо будет с этим разобраться
return $return ?? new SupplyEdgeProduct();
}
/**
* Запись продукта из 1С (поставка)
*
* @see Supply
*
* @todo Понять что может храниться внутри "$model->onec['ЗначенияСвойств']['ЗначенияСвойства']" и переписать
* Разобраться и создать возможность загрузки от лица другого аккаунта
*/
public static function createModel1c($product): ?self
{
// Инициализация
$model = self::searchByOcid($id = (string) $product->Ид) ?? new self;
$account ?? $account = yii::$app->user->identity;
// Настройка
$model->ocid = $id ?? null;
$model->catn = (string) $product->Артикул;
$model->dscr = (string) $product->Описание;
$model->onec = self::xml2array($product->xml);
if (isset($model->onec['ЗначенияСвойств'])) {
// Свойства инициализированы
foreach ($model->onec['ЗначенияСвойств'] as $property) {
// Перебор всех свойств
if (is_array($property)) {
if (!empty($account->opts['import_sections_oem']) && $property['Ид'] === $account->opts['import_sections_oem']) {
// Если идентификатор свойства совпадает с указанным в настройках свойства хранящего OEM номера
// Настройка
$model->oemn = array_merge(self::searchOemn($property['Значение']), self::searchOemn((string) $product->Артикул));
}
}
}
}
// Запись
if ($model->save()) {
// Поставка успешно сохранена
return $model;
}
return null;
}
/**
* @param mixed|null $context
* @return array
*/
public function getExportFields1c($context = null) {
return $this->onec;
}
/**
* Инициализация продукта
*
* @param string $catn Артикул, каталожный номер
*/
public static function initEmpty(string $catn): Product|array
{
$oemn = self::searchOemn($catn);
if (count($oemn) === 1) {
// Передан только один артикул
if ($model = Product::searchByCatn($catn)) {
// Продукт уже существует
return $model;
}
// Запись пустого продукта
return Product::writeEmpty($catn);
}
// Инициализация
$models = [];
foreach ($oemn as $catn) {
// Перебор всех найденных артикулов
if ($model = Product::searchByCatn($catn)) {
// Продукт уже существует
// Пропуск итерации
continue; continue;
} }
// Запись // Инициализация
if ($model = Product::writeEmpty($catn)) { $amount = 0;
// Записано
// Запись в массив сохранённых моделей // Повторный перебор для поиска дубликатов
$models[] = $model; foreach ($supplies as &$supply4check) {
if ($supply == $supply4check) {
// Найден дубликат
// Постинкрементация счётчика
$amount++;
// Запись в реестр
$registry[] = $supply4check->catn;
}
}
// Запись количества для заказа
$supply->amnt = $amount;
}
// Поиск стоимости для каждой поставки
foreach ($supplies as $key => &$supply) {
// Перебор поставок
// Чтение стоимости
$cost = $supply->readCost();
if ($cost < 1) {
// Если стоимость равна нулю (явная ошибка)
// Удаление из базы данных
$this->deleteSupply($supply->readId());
// Удаление из списка
unset($supplies[$key]);
// Пропуск итерации
continue;
}
// Запись цены
$supply->cost = $cost['ЦенаЗаЕдиницу'] . ' ' . $cost['Валюта'];
}
return $supplies;
}
/**
* @return DocumentInterface[]
*/
public static function findDocuments1c(): ?array
{
// yii::$app->on(ApiController::EVENT_AFTER_EXPORT_ORDERS, self::afterExport1c());
$orders = self::searchByEdge(
from: 'account',
to: 'order',
edge: 'account_edge_order',
direction: 'INBOUND',
subquery_where: 'account_edge_order.type == "processed"',
where: ['sync' => false]
);
foreach ($orders as &$order) {
// Перебор заказов
// Запись о том, что синхронизация проведена
$order->sync = true;
$order->update();
}
return $orders;
}
/**
* @return OfferInterface[]
*/
public function getOffers1c(): mixed
{
// Инициализация
$supplies = [];
foreach ($this->jrnl as $key => $jrnl) {
// Перебор журнала
// if (isset($supplies[$key]) && $supplies[$key]['id'] !== $jrnl['target']) {
// // Запись уже существует и идентификаторы не совпадают
// $key .= '_du'
// // Реинициализация
// $supplies[$key]['id'] = $jrnl['target'];
// } else {
// // Инициализация
// }
if (($jrnl['action'] ?? null) === 'write') {
// Найдено событие записи товара к заказу
$supplies[$key]['id'] = $jrnl['target'];
$supplies[$key]['amount'] ?? $supplies[$key]['amount'] = 0;
++$supplies[$key]['amount'];
} else if (($jrnl['action'] ?? null) === 'delete') {
// Найдено событие удаления товара из заказа
$supplies[$key]['id'] = $jrnl['target'];
$supplies[$key]['amount'] ?? $supplies[$key]['amount'] = 0;
--$supplies[$key]['amount'];
} }
} }
return $models; file_put_contents('supplies.txt', print_r($supplies, true));
if (count($supplies) > 0) {
// Поставки были записаны
// Инициализация
$supplies_buffer = [];
foreach ($supplies as $id => $supply) {
// Перебор поставок
if ($supply['amount'] < 1) {
continue;
}
if ($response = Supply::searchById($supply['id'])) {
// Поставка найдена в базе данных
$supplies_buffer[] = $response;
}
}
return $supplies_buffer;
}
file_put_contents('AAAAAAAAAAAAAAAAAAA.txt', print_r(1, true));
return [];
} }
/** /**
* Поиск OEM номеров * Неизвестно для чего
*
* @param string $oemn Необработанная строка с OEM-номерами
* @param string $delimiters Разделители
*
* @todo НЕ ЗАБЫТЬ СДЕЛАТЬ НАСТРОЙКУ РАЗДЕЛИТЕЛЕЙ
*
* @return array OEM-номера
*/ */
public static function searchOemn(string $oemn, string $delimiters = '\s\+\/,'): array public function getRequisites1c(): void
{ {
// Инициализация // return true;
$catn = [];
// Конвертация
preg_match_all("/[^$delimiters]+/", $oemn, $catn);
return $catn[0];
} }
/** /**
* Запись цены из 1С * Получить контрагента (пользователя от лица которого происходит операция)
*/
public function setPrice1c($price)
{
}
/**
* @param $types
* @return void
*/
public static function createPriceTypes1c($types) {
}
/**
* offers.xml > ПакетПредложений > Предложения > Предложение > ХарактеристикиТовара > ХарактеристикаТовара
* *
* Характеристики товара * @return PartnerInterface
* $name - Наименование
* $value - Значение
*
* @param \Zenwalker\CommerceML\Model\Simple $specification
* @return void
*/ */
public function setSpecification1c($specification) { public function getPartner1c(): Account
}
/**
* Запись данных на случай ошибки при экспорте из 1С
*/
public function setRaw1cData($cml, $object): bool
{ {
return true; return yii::$app->user->identity ?? throw new Exception('Не удалось идентифицировать пользователя');
} }
/** public function getExportFields1c($context = null)
* Поиск по идентификатору из 1С
*
* @param string $ocid Идентификатор из 1С
*
* @return Supply|null
*/
public static function searchByOcid(string $ocid): ?Supply
{
return static::findOne([static::getIdFieldName1c() => $ocid]);
}
/**
* Чтение группы из 1С
*/
public function getGroup1c(): ?SupplyGroup
{
return new SupplyGroup();
}
/**
* Чтение названия поля в котором хранится идентификатор из 1С
*/
public static function getIdFieldName1c(): string
{
return 'ocid';
}
/**
* Поиск по OEM-номерам
*
* @todo Реализовать с помощью LIKE
*/
public static function searchByOemn(): array
{ {
return []; return [];
} }
/** /**
* Прочитать стоимость * Возвращаем имя поля в базе данных, в котором хранится ID из 1с
*
* @return string
*/ */
public function readCost(Product $product = null): array public static function getIdFieldName1c()
{ {
if (isset($product)) { return 'ocid';
return SupplyEdgeProduct::searchByVertex($this->readId(), $product->readId(), type: 'connect', limit: 1)['onec']['Цены']['Цена']; }
}
return SupplyEdgeProduct::search($this->readId(), type: 'connect', limit: 1)['onec']['Цены']['Цена']; public function setRaw1cData($cml, $object): void
{
}
protected static function afterExport1c(): void
{
file_put_contents('afterExport1c.txt', print_r(1, true));
}
/**
* Отправка уведомления
*/
public static function notification(string $text, string|null $type = Notification::TYPE_NOTICE): Notification|array|null
{
// Отправка
return Notification::_write($text, type: $type);
} }
} }

View File

@ -412,37 +412,12 @@ class Supply extends Product implements ProductInterface, OfferInterface
return null; return null;
} }
/**
* @param $types
* @return void
*/
public static function createPriceTypes1c($types) {
return 100;
}
/**
* offers.xml > ПакетПредложений > Предложения > Предложение > ХарактеристикиТовара > ХарактеристикаТовара
*
* Характеристики товара
* $name - Наименование
* $value - Значение
*
* @param \Zenwalker\CommerceML\Model\Simple $specification
* @return void
*/
public function setSpecification1c($specification) {
}
/** /**
* @param mixed|null $context * @param mixed|null $context
* @return array * @return array
*/ */
public function getExportFields1c($context = null) { public function getExportFields1c($context = null) {
return [ return $this->onec;
'Ид' => 'ocid',
'Наименование' => 'catn'
];
} }
/** /**
@ -515,9 +490,29 @@ class Supply extends Product implements ProductInterface, OfferInterface
/** /**
* Запись цены из 1С * Запись цены из 1С
*/ */
public function setPrice1c($price): mixed public function setPrice1c($price)
{ {
return true; }
/**
* @param $types
* @return void
*/
public static function createPriceTypes1c($types) {
}
/**
* offers.xml > ПакетПредложений > Предложения > Предложение > ХарактеристикиТовара > ХарактеристикаТовара
*
* Характеристики товара
* $name - Наименование
* $value - Значение
*
* @param \Zenwalker\CommerceML\Model\Simple $specification
* @return void
*/
public function setSpecification1c($specification) {
} }
/** /**
@ -545,7 +540,7 @@ class Supply extends Product implements ProductInterface, OfferInterface
*/ */
public function getGroup1c(): ?SupplyGroup public function getGroup1c(): ?SupplyGroup
{ {
return $this->group; return new SupplyGroup();
} }
/** /**