====== Наценка на товары ====== Некоторые интернет-магазины предлагают различные опциональные дополнительные услуги для заказываемых товаров, эти услуги выбираются пользователем на этапе оформления заказа в корзине и влияют на окончательную стоимость заказа. Например, интернет-магазин по продаже какого-то сложного оборудования может предлагать услугу по настройке оборудования, за которую к товарам должна добавляться наценка. {{:private:koding:hostcms:shop:cart:pasted:20170123-125133.png}} Для реализации подобного механизма можно использовать данное решение. Стандартного механизма для хранения наценки по каждому товару в корзине и заказе не предусмотрено, поэтому необходимо придумать механизм хранения этой информации. Изначально, когда заказ еще не создан будем хранить информацию о наценках в сессии, когда пользователь оформит заказ эта информация запишется в доп. свойство заказа и с помощью наблюдателей будет прикрепляться к товарам заказа. Цена товаров, для которых будет выбрана наценка, будет подменятся с помощью наблюдателя при выводе корзины, будут учитываться данные сессии или данные из доп. свойства заказа. ===== Константы ===== Добавляем константу ''MARKUP_FOR_TEST_PRODUCTS'' со значением равным величину наценки. ===== Доп. свойство для заказа ==== Идем в заказы интернет-магазина и добавляем новое доп. свойство с названием «Системная информация о наценках», типом «Большое текстовое поле» и XML-тегом ''markups'', запрещаем множественные значения. Это поле будет использоваться решением для хранения информации о наценках на товары заказа. ===== XSL-шаблон ===== В XSL-шаблон корзины добавить колонку для выбора товаров для наценки, например, так:
===== Наблюдатели ===== Для начала необходимо загрузить 4 наблюдателя. ==== Наблюдатель для вывода наценки в заказе и ЦА (1) ==== * Загружаем файл: [[private:koding:hostcms:modules:shop:cart:markup:additionalfields.php|/modules/shop/order/item/observer/additionalfields.php]] * Добавляем в bootstrap.php:Core_Event::attach('shop_order_item.onCallmarkup', array('Shop_Order_Item_Observer_AdditionalFields', 'onCallmarkup')); ==== Наблюдатель для подмены цены товара (2) ==== Загружаем файл: [[private:koding:hostcms:modules:shop:cart:markup:addmarkuptoprice.php|/modules/shop/item/controller/observer/addmarkuptoprice.php]] ==== Наблюдатель для прикрепления наценки к корзине (3) ==== Загружаем файл: [[private:koding:hostcms:modules:shop:cart:markup:attachmarkup.php|/modules/shop/cart/controller/show/observer/attachmarkup.php]] ===== Формы центра администрирования ===== Идем в раздел Системы → Формы центра администрирования, находим форму «Список товаров в заказе», добавляем к ней поле новое поле «Наценка» с ключевым полем ''markup'' и типом «Вычисляемое поле (Используется обратный вызов функции)». Это поле будет формироваться наблюдателем (1), подключенным в bootstrap.php и в центре администрирования должно выглядеть так: {{:private:koding:hostcms:shop:cart:pasted:20170123-150540.png}} * Необходимо обратить внимание, что стоимость товара здесь выводится с учетом наценки, а наценка выступает в качестве информационного поля. Для вывода цены без наценки можно использовать метод ''Shop_Order_Item_Observer_AdditionalFields::onCallprice_without_markup'', создав аналогично полю ''markup'' поле ''price_without_markup'', а оригинальное поле с ценой из форм ЦА удалить. При этом в карточке товара в заказе все равно будет выводится цена товара с наценкой. ===== ТДС корзины ===== ==== Настройки страницы ==== - Код вывода краткой корзины оборачиваем в наблюдатель: Core_Event::attach('Shop_Item_Controller.onAfterCalculatePrice', array('Shop_Item_Controller_Observer_AddMarkupToPrice', 'onAfterCalculatePrice'));После вывода:Core_Event::detach('Shop_Item_Controller.onAfterCalculatePrice', array(' Shop_Item_Controller_Observer_AddMarkupToPrice', 'onAfterCalculatePrice'));Должно быть так:Core_Event::attach('Shop_Item_Controller.onAfterCalculatePrice', array('Shop_Item_Controller_Observer_AddMarkupToPrice', 'onAfterCalculatePrice')); $Shop_Cart_Controller_Show ->xsl( Core_Entity::factory('Xsl')->getByName( Core_Array::get(Core_Page::instance()->libParams, 'littleCartXsl') ) ) ->couponText(Core_Array::get($_SESSION, 'coupon_text')) ->show(); Core_Event::detach('Shop_Item_Controller.onAfterCalculatePrice', array('Shop_Item_Controller_Observer_AddMarkupToPrice', 'onAfterCalculatePrice')); - В настройках ТДС в коде пересчета/обновления корзины добавляем код для обработки добавленного чекбокса. Перед циклом добавляем: $aMarkups = Core_Array::getSession('hostcmsCartMarkups', array());Внутри цикла: $markup = Core_Array::getRequest('markup_' . $oShop_Cart->shop_item_id); if (!is_null($markup)) { $aMarkups[$oShop_Cart->shop_item_id] = MARKUP_FOR_TEST_PRODUCTS; } elseif (isset($aMarkups[$oShop_Cart->shop_item_id])) { unset($aMarkups[$oShop_Cart->shop_item_id]); }После цикла: $_SESSION['hostcmsCartMarkups'] = $aMarkups; ==== Код страницы ==== - Перед оператором switch для разделения на шаги:Core_Event::attach('Shop_Item_Controller.onAfterCalculatePrice', array('Shop_Item_Controller_Observer_AddMarkupToPrice', 'onAfterCalculatePrice'));После:Core_Event::detach('Shop_Item_Controller.onAfterCalculatePrice', array('Shop_Item_Controller_Observer_AddMarkupToPrice', 'onAfterCalculatePrice')); - На 4-ом шаге внутри условия:if ($_SESSION['hostcmsOrder']['shop_payment_system_id']) {Перед вызовом ''Shop_Payment_System_Handler::execute'' добавляем:$oShopOrderPropertyList = Core_Entity::factory('Shop_Order_Property_List', $oShop->id); $oProperty = $oShopOrderPropertyList->Properties->getByTagName('markups'); if ($oProperty) { $_SESSION['hostcmsOrder']['properties'][] = $aProperty = array($oProperty->id, json_encode($_SESSION['hostcmsCartMarkups'], JSON_PRETTY_PRINT)); } Core_Event::attach('shop_order_item.onBeforeRedeclaredGetXml', array('Shop_Order_Item_Observer_AdditionalFields', 'onBeforeRedeclaredGetXml'));После вызова:Core_Event::detach('shop_order_item.onBeforeRedeclaredGetXml', array('Shop_Order_Item_Observer_AdditionalFields', 'onBeforeRedeclaredGetXml')); $_SESSION['hostcmsCartMarkups'] = array(); - Для ветки ''default'' перед выводом корзины добавляем:Core_Event::attach('Shop_Cart_Controller_Show.onBeforeRedeclaredShow', array('Shop_Cart_Controller_Show_Observer_AttachMarkup', 'onBeforeRedeclaredShow'));После:Core_Event::detach('Shop_Cart_Controller_Show.onBeforeRedeclaredShow', array('Shop_Cart_Controller_Show_Observer_AttachMarkup', 'onBeforeRedeclaredShow')); ===== Основной макет ===== Если в основном макете есть вывод краткой корзины, то его также нужно обернуть в следующий наблюдатель: Core_Event::attach('Shop_Item_Controller.onAfterCalculatePrice', array('Shop_Item_Controller_Observer_AddMarkupToPrice', 'onAfterCalculatePrice'));После вывода:Core_Event::detach('Shop_Item_Controller.onAfterCalculatePrice', array(' Shop_Item_Controller_Observer_AddMarkupToPrice', 'onAfterCalculatePrice')); Страницу создал Максим Засорин 23.01.17 в 12:33