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

Цена товара в валюте витрины из бекэнда

waResearchLab

Приветствую!

Был уверен, что если инициализировать нужный роутинг, то потом при получении продукта или коллекции с указанием параметра frontend => true, я получу продукт в том виде в котором он предназначен для установленной в роутинге витрины. Ан нет... Как была системная инфа, так и остается, без перевода в валюту установленной в роутинге витрины. Где я концептуально ошибся или может чего-то не доделал, не доглядел?

10 апреля 2016
  • Коллекция действительно вернёт продукт в том виде, в котором он предназначен для витрины (сгенерятся ссылки в нужном формате, вызовутся плагины по событию frontend_products, применится округление). Но это не всегда включает в себя изменение валюты и перевод цены в валюту фронтенда. Конвертируйте цены уже вне коллекции, используя `shop_currency()` или `shop_currency_html()`. Как это делается во всех темах дизайна, например.

    Коллекция подменяет валюту и цены товаров только если для текущей валюты фронтенда включено округление цен. Если не включено, товары вернутся как есть.

    Если интересно, то вот небольшая историческая справка. Исторически сложилось, что товары в шаблоны тем передаются без конвертации валют. На дворе было сказочное время, класс коллекции ничего не знал про валюты, а темы дизайна использовали `shop_currency_html()` прямо на месте (как впрочем и сейчас используют). Жили они долго и счастливо, пока поверх этого не стало нужно добавить округление цен. Чтобы не надо было менять никакие темы дизайна, округлять надо было в коллекции. И округлять так хитро, чтобы существующие в теме дизайна вызовы `shop_currency` ничего не заметили и не испортили. Пришлось научить коллекцию подменять валюту товара на валюту фронтенда и переводить все цены. Тогда темы можно было не менять. Это объясняет, почему коллекция иногда подменяет валюты товаров.

  • Syrnik.com 11 апреля 2016 06:20

    Это объясняет, но это все равно грустно. :(

  • waResearchLab 11 апреля 2016 06:21

    А... Вот оно что, Михалыч... Я-то было подумал что пока с официальным перевозчиком заминка, доберусь на велосипеде марки shop_currency, а он оказывается и есть официальный перевозчик :) Ну хорошо. Понял, принял. Спасибо.

    Касательно справки. Тоже все понятно. Правильный делаю вывод, что при создании класса про цены/валюты просто сразу недоглядели по недоразумению, а потом уж пришлось жить с этим? Или параметр frontend как раз тогда и появился когда вопрос с округлением встал?

  • Угу. Если бы не привязка к куче сторонних (и просто модифицированных) тем дизайна, то зоопарк с валютами, конвертацией и округлением был бы не таким пугающим.

    Параметр frontend был и раньше. Он с самого начала влиял на генерацию ссылок, которая у товара зависит от настройки роутинга для витрины.

  • waResearchLab 11 апреля 2016 06:43

    Совместимость... Пресловутая совместимость... Сколько психики она попортила многим людям )))

  • waResearchLab 12 апреля 2016 03:47

    Леонид, вернемся еще на минутку к этому впоросу... Я так понял, что коллекция отдается в валюте витрины только в том случае, когда в настройках валюты используемой на этой витрине установлено округление. Я правильно понял? Если да, то хоть тресни не могу получить валюту отличную от основной. Что делаю:

    Основная валюта рубль. В настройках магазина указал что буду вводить все цены в основной валюте. Создал еще одну витрину (на другом домене). Выставил там валюту Bangladeshi taka. В настройках валют задал курс 1 BDT = 3 RUB. Так же в настройках BDT указал "Округлять до 99" с галкой только вверх.

    Далее в бекэнде инициализирую правильный роутинг на нужную витрину. Проверяю просто: через $routing->getUrl получаю правильный URL товара на этой витрине. Но при этом смотрю в полученную коллекцию - цены в рублях...

  • Ага. Я понял, что случилось.

    Находясь в бекенде, нельзя (без хаков) получить такую вещь как "текущая выбранная валюта фронтенда". wa('shop')->getConfig()->getCurrency(false) в бекенде всегда возвращает основную валюту. Коллекция думает, что выбрана основная валюта, и никаких округлений не применяет.

    Но это не мешает вам пробежаться по списку товаров и сконвертить цену в любую валюту, какую надо. shop_currency() никуда не делась.

  • Как-то так?..

    $default_currency = wa('shop')->getConfig()->getCurrency(true);
    $frontend_currency = 'BDT'; // or whatever
    foreach($products as &$p) {
        foreach(array('price', 'min_price', 'max_price', 'compare_price') as $price_key) {
            $price = shop_currency($p[$price_key], $default_currency, $frontend_currency, false);
            $price = shopRounding::roundCurrency($price, $frontend_currency);
            $p[$price_key.'_'.$frontend_currency] = $price;
        }
    }
    unset($p);
  • waResearchLab 12 апреля 2016 04:31

    Да, я тож уж догадался... Леонид, спасибо!

  • waResearchLab 13 апреля 2016 22:46

    И все же... Если вдруг цена товара указана не в основной валюте магазина (если брать этот пример, то в BDT), то чудеса чудесные: валюта товара стоит BDT, а вот цена уже сконвертирована в рубли... И фиг поймешь, в какой валюте сумма. Но на этот случай казалось бы есть параметр frontend=>true. Пробуем... Ага, появилась зацепочка: в массиве продукта появились элементы unconverted_бла-бла-бла. Но если посмотреть на них внимательно

    [currency]	RUB	
    [price]	59400.0000	
    [min_price]	59400.0000	
    [max_price]	60600.0000	
    .....
    [unconverted_currency]	BDT	
    [unconverted_price]	59400.0000	
    [unconverted_min_price]	59400.0000	
    [unconverted_max_price]	60600.0000	

    При этом смотрим на товар, и видим

    Курс, как я писал выше, 1 к 3. Все верно :) Круг замкнулся.

  • waResearchLab 13 апреля 2016 23:18

    Хотя нет, не замкнулся. Вывернуться можно, но ошибка, как мне видится, налицо. Было б неплохо если б в 7 версии порядок в этой части навели, а то мало ли что )

  • Не должно быть проблем.

    Цены товаров и артикулов могут храниться либо в валюте товара, либо в основной валюте магазина. Те, которые в основной валюте, коллекция никуда не конвертирует (но может немного подкорректировать, чтобы обеспечить округление). Коллекция конвертирует только цены, которые изначально указаны в валюте товара (product.currency). Но поскольку само поле product.currency тоже подменяется, код плагинов и тем не должен ничего заметить.

    Вот список полей с указанием, в какой валюте они хранятся. Я скопировал из комментов к моделям shopProductModel и shopProductSkusModel.

    product.price                      // primary shop currency
    product.min_price                  // primary shop currency
    product.max_price                  // primary shop currency
    product.compare_price              // primary shop currency
    product.total_sales                // primary shop currency
    sku.primary_price                  // primary shop currency
    
    product.compare_price_selectable   // product.currency
    product.base_price_selectable      // product.currency
    product.purchase_price_selectable  // product.currency
    skus.price                         // product.currency
    skus.purchase_price                // product.currency
    skus.compare_price                 // product.currency
  • waResearchLab 14 апреля 2016 06:24

    Постойте, постойте, Леонид.... Тут какое-то недопонимание... ))

    Вы ж видите что цифры одинаковые, а валюты разные... Это не опечатка.

    [currency]      RUB     
    [price] 59400.0000      
    [min_price]     59400.0000      
    [max_price]     60600.0000      
    .....
    [unconverted_currency]  BDT     
    [unconverted_price]     59400.0000      
    [unconverted_min_price] 59400.0000      
    [unconverted_max_price] 60600.0000    
  • ITFrogs 14 апреля 2016 06:37

    Павел, ты молодец. Лично я уже устал пытаться все это понять :)

  • waResearchLab 14 апреля 2016 06:56

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

  • > цифры одинаковые, а валюты разные

    Эти поля всегда в основной валюте магазина и не зависят от product.currency. До конвертации и после конвертации. Поэтому они и не поменялись. См. мой предыдущий пост. Так и должно быть.


  • Конвертация валюты, которую производит коллекция, нужна не для того, чтобы все цены перевести в валюту фронтенда. Она нужна для другого. Она модифицирует поля товара, чтобы сделать вид, что валюта товара изначально совпадала с валютой фронтенда. Эта операция не трогает цены, которые изначально по разным причинам должны храниться в валюте по умолчанию.

  • waResearchLab 14 апреля 2016 07:54

    Ну да... Вроде все верно. Видимо, отправная точка была ошибочной. А была она такой: product.currency в валюте товара, а product.price в основной валюте магазина. Но сам пока такую ситуацию не видел, а вот Андрей (ITFrogs) столкнулся. Будем наблюдать.

    P.S. При таком раскладе суть полей [unconverted_*] так и не понял. Но еще подумаю )

  • ITFrogs 14 апреля 2016 08:07

    Многие импортируют товары какими-то кустарными методами из 1с. Всяко может быть.

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

  • > суть полей [unconverted_*]

    В некоторых случаях unconverted_price не совпадает с price. Это глубочайшее тёмное шаманство, связанное с историческими сложностями введения округления.

    Чтобы показать цену в валюте фронтенда, тема дизайна конвертит её из основной валюты с помощью shop_currency(). Так всегда было исторически. Чтобы ввести округление без изменения кода тем, пришлось для каждого товара перевести цену из ОВ в ВФ, округлить, а потом перевести обратно из ВФ в ОВ. Так что при применении округления price перестаёт совпадать с unconverted_.

  • waResearchLab 14 апреля 2016 11:09

    Ну вроде наступает какой-то просвет в осознании происходящего.... Весь сыр-бор, как мне видится, из-за того, что сколько и как не говори

    $product = new shopProduct($id)
    
    или же
    
    $product = new shopProduct($id, true)

    цены (pricе, min, max) будут возвращаться уже отконвертированными. Но при этом в первом случае $product['currency'] будет валютой товара, а во втором - основная валюта магазина. Собственно это и вызывает необъяснимое чувство тревоги у неподготовленного обывателя :)

    Леонид, спасибо за разъяснения.



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