Закрыть
Скидки в Webasyst 25–29 ноября 2021

Cоздание товара. 7 версия.

waResearchLab

Приветствую!
Что-то я подзапутался... Хелп. Задача: создать товар. Все исходные данные на руках. Ситуация:

Создаем и сохраняем товар штатными средствами:

$prd = new shopProduct ();
$prd->save ( $data );

И вроде бы все хорошо, вот только у продукта нет $prd['sku_id']. Ну не беда, собираю нужные данные в массив $data_sku и говорю

$sku_model = new shopProductSkusModel ();
$sku = $sku_model->add($data_sku);
.....

Но вот тут-то и появляется подвох в виде записи в php.log

PHP Notice: Undefined index: in /var/www/debug/wa-apps/shop/lib/model/shopProduct.model.php on line 785

Глядя в указанном направлении, вижу что модель хочет поиметь

$skus[$product['sku_id']]['price']

а как говорилось выше этого $product['sku_id'] пока что нет, и собственно его я и создаю...

Собственно, вопрос: где я ошибаюсь?


30 мая 2016
  • waResearchLab 30 мая 2016 12:46

    Что-то я сразу не догадался с 6 версией-то сравнить... А там все в норме, никаких notice. Стало быть это просто ошибка.

  • Вижу баг в классе shopProduct. Если не передать артикул, то новый товар сохраняется без артикулов. Так быть не должно, должен создаваться пустой артикул по умолчанию. Ну и, ессно, никаких нотисов быть не должно. Это я исправлю в очередном патче магазина.

    Пока могу предложить workaround.

    $prd = new shopProduct ();
    $prd->save ($data + array(
        'skus' => array(
            -1 => array('name' => ''), // или передать тут честные параметры SKU
        ),
    ));
  • ODe 6 июня 2016 20:25

    Спасибо!

    Пока могу предложить workaround.

    Очень своевременно, без этого метод работал безумно долго, теперь не придется разбираться, почему :)

  • ITFrogs 7 июня 2016 00:23

    Нашел еще одно следствие этого бага, которое носит катастрофический характер, но, на первый взгляд, не заметно.

    Мы редактируем товар и заносим цену в артикул. Ранее эта цена переносилась в сущность товара. Сейчас этого не происходит. Если человек конвертнул цены из долларов в гривны например, то артикулы конвертнутся, а в товарах останутся старые цифры.

    Насчет конвертации это предположение. Но сейчас у конкретного клиента вижу в базе рассинхрон между артикулами и товарами. Причем при сохранении товара цены артикула меняются в базе, цены товара остаются старыми.

  • Каким способом происходит редактирование цен артикулов, что цены товара не меняются?

    В 7.0.2 был баг в shopProductMassUpdate, что сохранение цены артикула не меняло цены товара. Воспроизводилось при редактировании в списке в бекенде или через мобильное приложение. Но это должно было исправиться в 7.0.3.

    Через shopProduct цены всегда сохранялись корректно, насколько я знаю.

  • > без этого метод работал безумно долго

    Кстати! Если у вас массовое обновление цен и остатков, целесообразно посмотреть в сторону shopProductMassUpdate вместо shopProduct. Массовое сохранение должно работать гораздо шустрее. Тыщи мильёнов строк за раз, конечно, не осилит, но пачками по 50 товаров вполне справится.

  • ODe 7 июня 2016 19:26

    Кстати! Если у вас массовое обновление цен и остатков, целесообразно посмотреть в сторону shopProductMassUpdate вместо shopProduct.

    Ну тут у меня как раз штучные добавления товаров в каталог.

    А так этот класс я уже смотрела и баг с ценой как раз всплыл. Думала, что и тут проблема была где-то в моем коде, так что временно отказалась от него в пользу прежнего способа. Что ж, попробую еще разок.

    Но в shopProductMassUpdate еще одна проблема есть: в некоторых исключениях вы включаете в текст сообщения проблемную переменную. Так вот, я случайно передала массив куда не надо и заработала internal server error :) Исправить бы это.

  • ITFrogs 7 июня 2016 19:52

    Леонид, я досконально не расследовал т.к. был доступ только на фтп и было не особо удобно. Но я определил, что связь между артикулами и товарами разрушена. Причем движок без левого вмешательства. Думал, что нажатие на кнопку "Сохранить" поправит таблицы, но нет.

  • km 18 июня 2016 14:16

    shopProductMassUpdate - это с семерки?

  • Syrnik.com 18 июня 2016 17:07

    да, с семёрки

  • Александр 21 июня 2016 21:21

    Добрый день господа. Как продвигается решение вопроса:

    Нашел еще одно следствие этого бага, которое носит катастрофический характер, но, на первый взгляд, не заметно. Мы редактируем товар и заносим цену в артикул. Ранее эта цена переносилась в сущность товара. Сейчас этого не происходит. Если человек конвертнул цены из долларов в гривны например, то артикулы конвертнутся, а в товарах останутся старые цифры.

    Я тот клиент у которого это все не ладится. Могу дать доступы к чему угодно. Сейчас стоит задача до конца лета сделать полноценный сайт для оптовика, но плагины от Андрея не работают из за бага выше. Жду ответа, спасибо!

  • ITFrogs 21 июня 2016 22:02

    Я думал с последним обновлением все заработало как надо. Я там уже из товара цену не беру. Только из артикула.

  • Александр 21 июня 2016 23:48

    Нет, все та же беда с конвертацией.

  • Подтверждаю конвертация не работает.

  • Где какая конвертация не работает-то? Мне никто не ответил на самый главный вопрос))

    Каким способом происходит редактирование цен артикулов, что цены товара не меняются?

  • Если я правильно подставил икс и игрек в уравнение, то происходит вот это:

    shopRounding::roundCurrency(
        shop_currency('130.000', 'USD', 'RUB', false),
        'RUB'
    )

    Мы переводим $130 в рубли (по курсу 65) и округляем по правилам рублей. Должно получиться 8450. На моей машине одинаково в последней версии фреймворка и в 1.5.6...

  • waResearchLab 8 июля 2016 15:30

    Хм, а и вправду что-то с конвертацией случилось. Случайно наткнулся, стал смотреть. Если честно - приподза....мучался. Сухой остаток:

    Есть такой кусок кода

    $currency_price = shopRounding::roundCurrency(shop_currency($product[$type_price], $product->currency, $r['currency'], false), $r['currency']);

    где

    $product[$type_price] = 130.000 (это уже рубли, в товаре цена стоит 2 USD)
    $product->currency = USD
    $r['currency'] = RUB

    В настройках витрины рубли. В настройках валют "вводить в разных", не округлять, курс 65 р.

    Так вот в версии фреймворка 1.5.6.17 результат будет 130. А в текущей версии фреймворка 8450.

  • waResearchLab 8 июля 2016 15:33

    Леонид, я тут удалял то что написал, т.к. решил еще раз проверить все.... Ан нет, все как написал, поэтому восстановил. Новый фреймворк + SS7 = 8450. Новый фреймворк + SS6 = 8450. Старый фреймворк + SS6 = 130. Старый фреймворк + SS7 = уже не помню...

  • Я не могу поверить, что приведённый кусок кода на одних и тех же входных данных выдаёт разный результат в SS6+старый фреймворк и SS7+новый фреймворк. По крайней мере у меня воспроизвести не получилось.

    Предполагаю, что параметры функции shop_currency() различаются. Скорее всего, одном случае $product->currency возвращает одно, а в другом другое. И смотреть надо туда, откуда берётся $product и в какой момент происходит расхождение.

  • waResearchLab 8 июля 2016 15:55

    Блин... Хорошо. Действительно, валюта у товара разная в одном и другом случае. Когда писал смотрел из под отладчика, а старая версия на удаленном сервере. Сейчас проверил - вы правы, валюта разная. Но товар внешне выглядит одинаково. На локальную установку переносил его экспортом с удаленного сервера. В бекэнде в режиме редактирования и там и там стоит цена 2 USD.

    Откуда тогда берется другая валюта? Прям дежавю какое-то... )))

  • Проверьте, что настройки округления рублей у вас на обеих установках одинаковые.

    Хитрость в том, что $product->currency (вместе со всеми ценами) подменяется на валюту фронтэнда, но только когда для валюты фронтэнда включено округление. Кажется, я даже описывал механизм в дежавю по вашей ссылке :)

  • waResearchLab 8 июля 2016 16:05

    Мда... Все верно. Фишка в округлении рублей. Это невозможно понять... ))) Распечатаю, повешу на стенку :)

    Тогда пардон. С моей стороны паника отменяется. Но недопонимание этого шаманства все равно остается :)

    А как получить гарантированный результат? Добавить условие проверки установлено ли округление основной валюты магазина или нет?

  • Ничего не надо плагину знать про округление. А надо только не путаться в валютах. Что тоже может быть не просто :)

    Магазин всегда придерживается правил:

    1) product.price, .compare_price, .min_price, .max_price - в основной валюте магазина.

    2) sku.price, .purchase_price, .compare_price - в валюте товара (product.currency).

    3) sku.primary_price - в основной валюте магазина.

    Если происходит чёрная магия по переводу из валюты в валюту, округление и т.п., то product.currency и значения цен всегда меняются только вместе. Плагинам должно быть всё равно, произошло округление или нет: с точки зрения плагина ему просто пришёл товар в одной валюте или в другой; с одними ценами или с другими. И предоставляя товар на выход, плагин тоже должен выполнять эти условия. Тогда и другие плагины, и темы дизайна, которые ожидают выполнения этих условий, не сломаются.

    Если ваш $product[$type_price] - это product.price или product.compare_price, то переводить его нужно не из product.currencу, а из основной валюты магазина: wa('shop')->getConfig()->getCurrency(true).

  • waResearchLab 8 июля 2016 17:39

    Хм... А валюта витрины тут вообще никак не участвует? На всякий случай уточню: там парой строк выше идет проверка "если валюта товара не равна валюте витрины, то понеслась". Т.е. надо проверять соответствие валюты товара валюте магазина? Тоже не понимаю... В данном конкретном примере валюта магазина = валюте витрины и не равна валюте товара.

    Хорошо. Взял себя в руки, провел еще пучок экспериментов. Убрал все конвертации. Валюта магазина - рубли. Валюта товара - доллары. Попробовал с витриной валютой которой установлены рубли. Получил цену 130, как и положено. И с округлением и без. Создал еще одну витрину. Сделал валютой этой витрины доллары. Получил 130 (вне зависимости от округления). Т.е. просто цену не взять, т.к. для разных витрин с разными валютами получаю одинаковые значения. Стало быть нужны проверки и конвертация.

    Далее... Вернул эту конвертацию обратно. Включил округление. Попробовал. Для долларовой витрины получил 2, для рублевой 130.

    Теперь выключил округление. Для долларовой витрины получил 130. Для рублевой 8450.

    Убрал из той строки переменную возвращающую валюту витрины и поставил просто 'RUB' (валюта магазина). Получил: для долларовой 130, для рублевой 8450. Это без округления основной валюты магазина. Включил округление. Получил: для долларовой 130, для рублевой 130.

    В этот момент случилось мимолетное озарение, и я обратил внимание на фразу

    переводить его нужно не из product.currencу, а из основной валюты магазина

    Снова изменил строку конвертации, приведя ее к такому виду

    $currency_price = shopRounding::roundCurrency(shop_currency($product[$type_price], 'RUB', $r['currency'], false), $r['currency']);

    Получил: с округлением основной валюты магазина - все чин чинарем. Без округления - и для рублевой и для долларовой по 130.

    Т.е. получается.... А я уже не понимаю что получается и как это проверять ))))

    На всякий случай: вся свистопляска происходит в бекэнде, роутинг инициализируется вручную, $product[$type_price] это min_price, исходники локально, фреймворк локально, монитор чистый, на клавиатуре пара капель мозга.


  • waResearchLab 8 июля 2016 17:51

    Вдогонку... Тут еще луч света проскользнул, и обратил внимание что описанные в предыдущем комментарии тесты проводил с проверкой соответствия валюты товара валюте витрины. Изменил условие. Поставил проверку соответствия валюты товара валюте магазина. Не вдаваясь в подробности - все хорошо за исключением долларовой витрины: при включенном округлении основной валюты магазина. В этом случае отдает 130.

  • В плохом случае долларовой витрины при включённом округлении рублей: что выведет такая штука?

    wa_dump(
        $r['currency'],
        $product[$type_price],
        $product->currency,
        (new shopProduct($product->getId(), true))[$type_price],
        (new shopProduct($product->getId(), true))->currency // PHP5.4+
    );
    

    Это я хочу сравнить имеющийся $product с чистым и свежим объектом, чтобы удостовериться, что никто туда ничего не присваивал.

  • waResearchLab 8 июля 2016 18:08

    Вот. Если я правильно понял "плохой случай".

    dumped from /var/www/debug/wa-apps/shop/plugins/vkgoods/lib/classes/shopVkgoodsPluginPublish.class.php line #666:
    'USD'
    '130'
    'RUB'
    '130'
    'RUB'
  • Похоже на правду. То есть происходит буквально вот это:

    shopRounding::roundCurrency(shop_currency('130', 'RUB', 'USD', false), 'USD')

    Но тогда 130 из рублей в $ должно быть 2. А у вас 130? О_о

  • waResearchLab 8 июля 2016 18:46

    Мда.... Дела... В общем вот он ответ на все мои вопросы

    Ничего не надо плагину знать про округление. А надо только не путаться в валютах. Что тоже может быть не просто :)

    Не надо было возвращать проверки соответствия валют товара и магазина, и делать конвертацию в любом случае. Пусть даже из рублей в рубли.

    Как бы это сказать-то.... Ну в общем вопрос закрыт пока снова на эти грабли не наступлю )) Леонид, спасибо за терпение :)



Чтобы добавить комментарий, зарегистрируйтесь или войдите