JoomShopping 5.х - сохранение параметров магазина затирает данные
Столкнулись с проблемой, после установки дополнений, сохранении параметров магазина стирает все данные кроме выбранной вкладки. Например настраиваем товары, при этом стираются "функции магазина", " товары" и тд. Все это происходит из-за не корректной работы плагинов по событию "onBeforeEditConfig..." и "onAfterEditConfig..."
В момент сохранения к выбранным парамтрам(страница параметров магазина) добавляются пустые значения остальных параметров и весь этот полу-пустой массив сохраняется в базу.
Решение:
1.Редактируем файл с процедурой подготовки данных:
Возникла необходимость объеденить заказы одного или нескольких человек в один, причем со сложением одинаковых товаров - по ид, артикулу, атрибуту, но стоимость брать минимальную по списку.
Нам понадобился собственный отчет и клиент попросил добавить его в пункты Joomshopping, что нужно сделать:
1.В базе создать пункт меню для меню "Компоненты" таблица #__menu, заполнить
menutype - main title - <название> alias - <название в анг.> path - joomshopping/<alias> link - option=com_jshopping&controller=<папка в каталоге JS/views> type - component piblished - 1 parent_id - <id строки JS c alias=joomshopping> level - 2 component_id - <Id JS> lft - взять максимальное значение rgt - взять максимальное значение+1
2.Создать папку в админ каталоге JS administrator\components\com_jshopping\views\<alias>\
Разместить файл view.html.php
defined('_JEXEC') or die('Restricted access'); jimport( 'joomla.application.component.view');
class JshoppingViewReport extends JViewLegacy { function display($tpl=null){ $layout = $this->getLayout(); $title = 'Отчет'; parent::display($tpl); } }
Эта страница дополнительной настройки компонента RAD JS YML
Особености ведения нескольких моделей магазина
В компоненте вы можете отдельно вести ADV и DBS компанию, можно вести сразу 2 компании, особеность настройки - добавление региона и назначение одного из них "регионом DBS"
Если вы ведете только ADV компанию, то вам нужно в парамтерах "Яндекс.API" пункт "Регин DBS модели" выбрать "Не используется"
Для настройки DBS нужно выбрать регион или использовать основной регион (работать без регионов)
Дополнительные возможности DBS модели
Для DBS модели яндекс назначает своюю коммисию, вы можете создать наценку нас стоимость товара для покрытия издержек, в параметрах товара поле "Наценка DBS"
Поступила задача предоставить скику от суммы и кол-ва заказов.
Для реализации создадим файл с функцией расчета скидки
<pre><?php<br />function get_raddicount($userid=0,$bilsum=0,$retval='',$ignoreorderid='')<br />{<br /> $_SESSION['rad_discount_before']=$bilsum;<br /> $_SESSION['rad_discount_name']='';<br /> //пользователь без регистрации -Basa - скидка от суммы заказа<br /> if ($userid==0)<br /> {<br /> if ($bilsum>=5000) {$total_discotun=$bilsum*0.03;$discount_name='скидка 3%';}<br /> if ($bilsum>=7500) {$total_discotun=$bilsum*0.05;$discount_name='скидка 5%';}<br /> if ($bilsum>=10000) {$total_discotun=$bilsum*0.07;$discount_name='скидка 7%';}<br /> if ($bilsum>=15000) {$total_discotun=$bilsum*0.1;$discount_name='скидка 10%';}<br /> }<br /> //пользователь зареган смотрим кол-во закаов<br /> if ($userid*1>0)<br /> {<br /> $db = JFactory::getDbo(); <br /> $query="select count(*) from #__virtuemart_orders <br /> where virtuemart_user_id='".$userid."' and order_total>0<br /> ".(($ignoreorderid!='')?" and virtuemart_order_id not in (".$ignoreorderid.")":'')." ";<br /> $db->setquery($query);$ordcount=$db->laodresult();<br /> //закзов нет - общая схема по сумме<br /> if ($ordcount==0)<br /> {<br /> if ($bilsum>=5000) {$total_discotun=$bilsum*0.03;$discount_name='скидка 3%';}<br /> if ($bilsum>=7500) {$total_discotun=$bilsum*0.05;$discount_name='скидка 5%';}<br /> if ($bilsum>=10000) {$total_discotun=$bilsum*0.07;$discount_name='скидка 7%';}<br /> if ($bilsum>=15000) {$total_discotun=$bilsum*0.1;$discount_name='скидка 10%';}<br /> }<br /> //есть заказы<br /> if ($ordcount>0)<br /> {<br /> if ($ordcount==1) {$total_discotun=$bilsum*0.03;$discount_name='скидка 3%';}<br /> if ($ordcount==2) {$total_discotun=$bilsum*0.05;$discount_name='скидка 5%';}<br /> if ($ordcount==3) {$total_discotun=$bilsum*0.07;$discount_name='скидка 7%';}<br /> if ($ordcount>=4) {$total_discotun=$bilsum*0.1;$discount_name='скидка 10%';}<br /> }<br /> }<br /> $_SESSION['rad_discount_name']=$discount_name;<br /> $_SESSION['rad_discount_total']=$total_discotun;<br /> //вывод<br /> if ($retval=='name') return $_SESSION['rad_discount_name']; else return $total_discotun;<br />}</pre>
Добавим пересчет стоимости заказа со скидка, файл
plugins/system/onepage_generic/cart/ajaxprice.php
<?php /** ** Parts of this code is written by joomlapro.com Copyright (c) 2012, 2015 All Right Reserved. ** Many part of this code is from VirtueMart Team Copyright (c) 2004 - 2015. All rights reserved. ** Some parts might even be Joomla and is Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved. ** http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php ** This source is free software. This version may have been modified pursuant ** to the GNU General Public License, and as distributed it includes or ** is derivative of works licensed under the GNU General Public License or ** other free or open source software licenses. ** ** THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY ** KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE ** IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A ** PARTICULAR PURPOSE. ** <author>Joomlaproffs / Virtuemart team</author> ** <email>Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.;/email> ** <date>2017</date> */ defined('_JEXEC') or die('Restricted access'); include_once(JPATH_ROOT.DIRECTORY_SEPARATOR.'radfunc.php'); $cart->prepareCartData(); $i = 0; foreach($cart->pricesUnformatted as $id=>$value) { if(!is_array($value) && is_string($id)) { continue; } $price_values["products"][$id]["subtotal_salesPrice"]=!empty($cart->pricesUnformatted[$id]["salesPrice"])?$currency->priceDisplay($cart->pricesUnformatted[$id]["salesPrice"]):""; $price_values["products"][$id]["subtotal_tax_amount"]=!empty($cart->pricesUnformatted[$id]["taxAmount"])?$currency->priceDisplay($cart->pricesUnformatted[$id]["taxAmount"], 0, $cart->products[$id]->quantity):""; $price_values["products"][$id]["subtotal_discount"]=!empty($cart->pricesUnformatted[$id]["subtotal_discount"])?$currency->priceDisplay($cart->pricesUnformatted[$id]["discountAmount"], 0, $cart->products[$id]->quantity):"";
//изменение стоимости на группу $user = JFactory::getUser(); $rad_discount_sum=get_raddicount($user->id,$cart->pricesUnformatted["billTotal"]); $cart->pricesUnformatted["billTotal"]=$cart->pricesUnformatted["billTotal"]*1-$rad_discount_sum; $price_values["discountname"]=$_SESSION['rad_discount_name'];
Функция собирающие все дерево из представленного списка:
function get_cat_tree($rows,$lvlstr,$parentid,$prodmass) { $ret='';$show=0;if (!isset($childmass)) $childmass=array(); foreach($rows as $item_op) { if ($item_op->category_parent_id==$parentid) { $ret.=' <div class="vmcatname vmcatname_'.$item_op->virtuemart_category_id.' dsn" onclick="jQuery('."'.tovmas'".').hide();jQuery('."'.tovmas_".$item_op->virtuemart_category_id."'".').show();">'; if (isset($prodmass[$item_op->virtuemart_category_id]) and count($prodmass[$item_op->virtuemart_category_id])>0) $ret.='<span class="updwar icon-arrow-down-3"> </span>'; $ret.='<h4>('.$item_op->virtuemart_category_id.')'.$lvlstr.$item_op->name; if (isset($prodmass[$item_op->virtuemart_category_id]) and count($prodmass[$item_op->virtuemart_category_id])>0) $ret.='<span class="reddiv_ reddiv_'.$item_op->virtuemart_category_id.'"> ('.count($prodmass[$item_op->virtuemart_category_id]).')</span>'; $ret.='</h4> </div>'; $retmass=get_cat_tree($rows,$lvlstr.' - ',$item_op->virtuemart_category_id,$prodmass); $ret.=$retmass['str'];
if (isset($retmass['chlidmass']) and count($retmass['chlidmass'])>0) $childmass=array_merge($childmass, $retmass['chlidmass']); //дочерняя ветка имеет товары if ($retmass['show']==1) { $show=1; //$ret.='<div>['.$item_op->virtuemart_category_id.'] has - child</div>'; $childmass[]=$item_op->virtuemart_category_id; if ($item_op->category_parent_id>0) $childmass[]=$item_op->category_parent_id; } //блок товаров if (isset($prodmass[$item_op->virtuemart_category_id]) and count($prodmass[$item_op->virtuemart_category_id])>0) { $ret.='<div style="display:none" class="tovmas tovmas_'.$item_op->virtuemart_category_id.'"><ul class="tovmassul">'; foreach($prodmass[$item_op->virtuemart_category_id] as $item) $ret.= $item; $ret.='</ul></div>'; $show=1;$childmass[]=$item_op->virtuemart_category_id; if ($item_op->category_parent_id>0) $childmass[]=$item_op->category_parent_id; } } } $childmass=array_unique($childmass); return array('str'=>$ret,'show'=>$show,'chlidmass'=>$childmass); }
Вызов:
$db = JFactory::getDbo(); $db->setQuery(" select v.virtuemart_category_id,v.category_parent_id, (select category_name from #__virtuemart_categories_ru_ru vv where vv.virtuemart_category_id=v.virtuemart_category_id) as name from #__virtuemart_categories v order by name ");$cat_lists = $db->loadObjectList(); ..... if (count($cat_lists)>0) { $tree=get_cat_tree($cat_lists,'',0,$prodmass); $txt=$tree['str']; foreach($tree['chlidmass'] as $item) $txt=str_replace('vmcatname_'.$item.' dsn','vmcatname_'.$item.'',$txt); echo $txt; }
В данном примере мы прячем ветки, без товаров через css.
JoomShopping загрузка файла к заказу (чек, реквизиты)
Часто магазину требуется загрузить файлы клиента к заказу, например pdf файл с реквизитами, у joomshopping нет такого функционала, но его можно добавить.
Для загрузки файлов будем использовать aJax библиотеку plupload
5.Добавить колонку fn в таблицу #__jshopping_orders
6.Добавить обработку при сохранении заказа
coponents/com_jshopping/models/checkoutorder.php
функция orderDataSave(&$adv_user, &$post)
if (isset($_SESSION['orderfn']) and strlen($_SESSION['orderfn'])) { $file=JPATH_ROOT.DS.'tmp'.DS.$_SESSION['orderfn']; $new_name=JPATH_ROOT.DS.'user_files'.DS.$order->order_id.DS.$_SESSION['orderfn']; if (!file_exists(JPATH_ROOT.DS.'user_files'.DS.$order->order_id)) {mkdir(JPATH_ROOT.DS.'user_files'.DS.$order->order_id, 0777, true);} if (rename($file, $new_name)) { $db->setquery("update #__jshopping_orders set fn='".$order->order_id.DS.$_SESSION['orderfn']."' where order_id='".$order->order_id."' ");$db->execute(); } }
Стандартная сортировка атрибутов настраивается в самом атрибуте, но иногда возникает потребность в более тонкой сортировке, например у вас есть 2 цвета белый и хром, на белый цвет нужно добавить наценку +900р, и он должен стоять вторым в списке, стандартными средствами этого не сделать.
Для настройки нужно добаить колонку `orders` в таблицу #__jshopping_products_attr2
function getAttribValue($attr_id, $other_attr = array(), $onlyExistProduct = 0){ $jshopConfig = JSFactory::getConfig(); $allattribs = JSFactory::getAllAttributes(1); $lang = JSFactory::getLang(); if ($allattribs[$attr_id]->independent==0){ $where = ""; foreach($other_attr as $k=>$v){ $where.=" and PA.attr_".(int)$k."=".(int)$v; } if ($onlyExistProduct) $where.=" and PA.count>0 "; $sorting = $jshopConfig->attribut_dep_sorting_in_product; if ($sorting=="") $sorting = "V.value_ordering"; $field = "attr_".(int)$attr_id; $query = "SELECT distinct PA.$field as val_id, V.`".$lang->get("name")."` as value_name, V.image FROM `#__jshopping_products_attr` as PA INNER JOIN #__jshopping_attr_values as V ON PA.$field=V.value_id WHERE PA.product_id=".(int)$this->product_id." ".$where." ORDER BY ".$sorting; }else{ $sorting = $jshopConfig->attribut_nodep_sorting_in_product; if ($sorting=="") $sorting = "V.value_ordering"; $query = "SELECT PA.attr_value_id as val_id, V.`".$lang->get("name")."` as value_name, V.image, price_mod, addprice,PA.`orders` FROM `#__jshopping_products_attr2` as PA INNER JOIN #__jshopping_attr_values as V ON PA.attr_value_id=V.value_id WHERE PA.product_id=".(int)$this->product_id." and PA.attr_id=".(int)$attr_id." ORDER BY ".$sorting.' asc ,PA.`orders` desc'; } extract(js_add_trigger(get_defined_vars(), "after")); $this->_db->setQuery($query); return $this->_db->loadObjectList(); }
В функцию getBuildSelectAttributes добавляем проверку на необходимость сортировки и переопределение первого элемента в массиве атрибутов:
function getBuildSelectAttributes($attributeValues, $attributeActive, $displayonlyattrtype = null,$product_id=0){ $jshopConfig = JSFactory::getConfig(); if (!$jshopConfig->admin_show_attributes) return array(); $dispatcher = JDispatcher::getInstance(); $attrib = JSFactory::getAllAttributes(); $userShop = JSFactory::getUserShop(); $selects = array();$attrorder=array(); $db = JFactory::getDBO(); if (isset($this) and isset($this->product_id) and $this->product_id*1>0) { $db->setquery("select a.*,(select `name_ru-Ru` from #__jshopping_attr_values v where v.value_id=a.attr_value_id and a.attr_id=v.attr_id) as name from #__jshopping_products_attr2 a where product_id='".$this->product_id."' ");$attrsdb=$db->loadobjectlist(); foreach($attrsdb as $attr) $attrorder[$attr->attr_id][$attr->name]=$attr->orders; } foreach($attrib as $k=>$v) { $attr_id = $v->attr_id; if ($displayonlyattrtype){$v->attr_type = $displayonlyattrtype;} if (isset($attributeValues[$attr_id]) && $attributeValues[$attr_id]) { if (isset($attributeActive[$attr_id])) { $_firstval = $attributeActive[$attr_id]; } else { $_firstval = 0; } $selects[$attr_id] = new stdClass(); $selects[$attr_id]->attr_id = $attr_id; $selects[$attr_id]->attr_name = $v->name; $selects[$attr_id]->attr_description = $v->description; $selects[$attr_id]->groupname = $v->groupname; $selects[$attr_id]->firstval = $_firstval; $selects[$attr_id]->attributeValues = $attributeValues[$attr_id][0]->orders; $options = $attributeValues[$attr_id]; $attrimage = array();$need_reorder=0; foreach($options as $k2=>$v2) { $attrimage[$v2->val_id] = $v2->image; $addPrice = $v2->addprice; $addPrice = getPriceFromCurrency($addPrice, $this->currency_id); $addPrice = getPriceCalcParamsTax($addPrice, $this->product_tax_id); if ($userShop->percent_discount) { $addPrice = getPriceDiscount($addPrice, $userShop->percent_discount); } $options[$k2]->addprice = $addPrice; $options[$k2]->orders = $v2->orders; $options[$k2]->val_id=$v2->val_id; if ($v2->orders*1>0) $need_reorder=1; } if ($need_reorder==1) { $options=self::sort_attr($options,'orders','asc');//сортировка //переназначаем первый элемент if ($selects[$attr_id]->firstval*1>0) { $selects[$attr_id]->firstval=$options[0]->val_id; $_firstval=$options[0]->val_id; $attributeActive[$attr_id]=$_firstval; } } if ($v->attr_type==1){ ...................
Далее вам нужна форма для редактирования поля `orders` - но это на ваше усмотрние.
Для восстановления пароля, нужно в таблице #__users в поле paasword вставить значение "d2064d358136996bd22421584a7cb33e:trd7TvKHx6dMeoMmBVxYmg0vuXEA4199" - это слово "secret"
JoomShopping &One Step Checkuot - своя стоимость доставки и самовывоза у товара
Интернет магазину часто необходимо указывать свою стоимость доставки/самовывоза, например для крупногабаритного груза, но стандартный функционал не позволяет это реализовать.
Для внедрения этого функционала необходимо в базе данных содать нужные поля - стоимость доставки(deleviry_cost) и стоимость самовывоза(pickup_cost).
Необходимо внести изменения в шаблон корзины One Step Checkout, файл:
В нашем случае самовывоз это shipping_id=1, все остальное это доставка(транспортной компанией, до квартиры и тд), необходимо внести изменения в блок с выводом стоимости, элемент <td class="name SHIPPING_PRICE">:
$totalpickup_cost=0;$delivery=0;//обнуляем общую стоимость до цикла вывода товаров в карточке foreach ($this->products as $key_id=>$prod) { if ($shipngid==1) { $db->setquery("select pickup_cost from #__jshopping_products where product_id='".$prod['product_id']."'");$pickup_cost=$db->loadresult(); if (trim($pickup_cost)=='') $pickup_cost='0'; $totalpickup_cost=$totalpickup_cost+($pickup_cost*$prod['quantity']); } if ($shipngid!=1) { $db->setquery("select yan_pickup_cost from #__jshopping_products where product_id='".$prod['product_id']."'");$delivery_cost=$db->loadresult(); if (trim($delivery_cost)=='') $delivery_cost='0'; $price=$price+($delivery_cost*1); $delivery=$delivery+($delivery_cost*$prod['quantity']); } if ($shipngid!=1) $this->summ_delivery=$delivery; if ($shipngid==1) $this->summ_delivery=$totalpickup_cost; if (isset($this->summ_delivery) and $this->summ_delivery>0) { ?> <tr> <td class="name SHIPPING_PRICE"> <?php if ($is_shiping) echo JText::_('JSHOP_ONESTEPCHECKOUT_SHIPPING_PRICE'); else echo 'Стоимость самовывоза' ?> <input type="hidden" id="formula" value="shipngid: <?php echo $shipngid?> qunt: <?php echo $qunt?> first: <?php echo $first?> second: <?php echo $second?> delcost: <?php echo $price?>"> </td> <td class="value SHIPPING_PRICE"> <?php echo formatprice($this->summ_delivery) ?> <?php echo $this->_tmp_ext_shipping?> <input type="hidden" id="pagequant" value="<?php echo $qunt?>"> <input type="hidden" id="delprice" value="<?php echo getRoundPriceProduct(floatval($price+$quntprice))?>"> </td> </tr> <tr style="display:none;"> <td class="name mkad">Выезд за МКАД: расстояние 1км/40руб</td> <td class="value SHIPPING_PRICE" id="mkadtd">40 руб.</td> </tr> <?php } ?>
Но это только шаблон корзины, также необходимо включить стоимость доставки при создании заказа, необходимо файле после создания заказа $order->saveOrderItem($cart->products) добавить код пересчета стоимости:
components/com_jshopping/models/checkoutorder.php
$order->saveOrderItem($cart->products); if ($order->shipping_method_id!='1')//доставка { $db->setquery("select sum(delivery_cost) from #__jshopping_products where product_id in (select product_id from #__jshopping_order_item where order_id='".$order->order_id."') ");$shipselfsumm=$db->loadresult(); $db->setquery("update `#__jshopping_orders` set order_shipping='".$shipselfsumm."' WHERE order_id='".$order->order_id."' ");$db->execute(); $db->setquery("update `#__jshopping_orders` set order_total=(order_shipping+order_subtotal+order_payment+order_package-order_discount) WHERE order_id='".$order->order_id."' ");$db->execute(); } if ($order->shipping_method_id=='1')//самовывоз { $db->setquery("select sum(pickup_cost) from #__jshopping_products where product_id in (select product_id from #__jshopping_order_item where order_id='".$order->order_id."') ");$shipselfsumm=$db->loadresult(); $db->setquery("update `#__jshopping_orders` set order_shipping='".$shipselfsumm."' WHERE order_id='".$order->order_id."' ");$db->execute(); $db->setquery("update `#__jshopping_orders` set order_total=(order_shipping+order_subtotal+order_payment+order_package-order_discount) WHERE order_id='".$order->order_id."' ");$db->execute(); }
Для изменения подписи "стоимость доставки" на "стоимость самовывоза" в шаблоне письма для покупателя, необходимо редактировать файл:
JoomShopping в своем стандартном функционале имеет возможность только предоставления скидки по купону, но возникает потребность делать подарки при покупке определенного товара.
Для реализации этого механизма вам необходимо вести 2 списка: Список товаров и список подарков к этим товарам. Пример составлен для дополнения one page checkout.
Нам необходимо внести изменения в файле корзины one page checkout:
Добавить код, для вставки формы добавления подарка:
<?php //выбор подарка //список товаров в $prodid //список включенных подарков в $gifts //товары в карточки $prodidstr //подарки в карточке $cartgiftsstr //смотрим в какие активные акции с типом подарок попадают товары $prodidstr=implode(',',$prodid); $cartgiftsstr=implode(',',$gifts); if (count($gifts)==0) $cartgiftsstr='0'; if (trim($cartgiftsstr)=='') $cartgiftsstr='0'; echo '<input type="hidden" id="prodstr" value="'.$prodidstr.'">'; if (trim($prodidstr)!='') { $db->setquery("select distinct discount_id,(select GROUP_CONCAT(list_id) from #__rad_market_js_list p where p.tp='tovm' and p.discount_id=l.discount_id) as gifts, (select name from #__rad_market_js_discounts d where d.id=discount_id) as name, (select def from #__rad_market_js_discounts d where d.id=discount_id) as def from #__rad_market_js_list l where list_id in (".$prodidstr.") and tp='tov' and discount_id in (select id from #__rad_market_js_discounts s where s.state=1 and `end`>DATE(NOW()) and s.tp='gift') ");$desclist=$db->loadobjectlist(); if (count($desclist)>0) { $ret= '<table style="width:100%;" class="gifttable"><tbody>'; $count=0; //список акций foreach($desclist as $dblist) { $giftsstr=$dblist->gifts;$mass=explode(',',$giftsstr);if (count($mass)==0)$mass=array($giftsstr);$newmass=array();foreach($mass as $massitem) if (trim($massitem)!='')$newmass[]=$massitem;$giftsstr=implode(',',$newmass); $desclistmass[$dblist->discount_id]=$newmass; } //смотрим какой список уже отработал $exlist=array(); if (trim($cartgiftsstr)!='') foreach($desclist as $dblist) foreach(explode(',',$cartgiftsstr) as $cartgid) if (in_array($cartgid, $desclistmass[$dblist->discount_id])) $exlist[]=$dblist->discount_id; foreach($desclist as $dblist) if (!in_array($dblist->discount_id,$exlist)) { $gfcount=0; if (trim($dblist->gifts)!='') { //отработка пустых значений $giftsstr=$dblist->gifts;$mass=explode(',',$giftsstr);if (count($mass)==0)$mass=array($giftsstr);$newmass=array();foreach($mass as $massitem) if (trim($massitem)!='')$newmass[]=$massitem;$giftsstr=implode(',',$newmass); $db->setquery("select (select GROUP_CONCAT(category_id) from #__jshopping_products_to_categories c where c.product_id=p.product_id limit 1) as catid,`name_ru-RU` as name,p.* from #__jshopping_products p where product_id in (".$giftsstr.") ");$dbgifts=$db->loadobjectlist(); //предварительный расчет кол-ва подарков на выбор foreach($dbgifts as $gift) if ((!in_array($gift->product_id,explode(',',$cartgiftsstr)))){$gfcount++;} //вывод формы if ($gfcount>0) { //заголовок $ret.='<tr><td colspan="3" id="doscunttr_'.$dblist->discount_id.'"><h3>'.$dblist->name.'</h3></td></tr>'; $ret.='<tr><td colspan="3" id="doscuntdeftr_'.$dblist->discount_id.'"><span style="color:red;">*При заказе данного товара мы предоставляем подарок</span></td></tr>'; if (trim($dblist->def)!='') $ret.='<tr><td colspan="3" id="doscuntdeftr_'.$dblist->discount_id.'"><pre>'.$dblist->def.'</pre></td></tr>'; //товары foreach($dbgifts as $gift) if ((!in_array($gift->product_id,explode(',',$cartgiftsstr)))) { $ret.='<tr> <td><img class="uk-thumbnail" src="'.JURI::root().'components/com_jshopping/files/img_products/thumb_'.$gift->image.'" style="max-height:100px;max- width:100px;"></td> <td>'.$gift->name.'</td> <td><a class="btn setgift uk-button" id="'.$gift->product_id.'"><span class="icoon-basket"></span>Выбрать</a></td> </tr>'; $gfcount++;$count++; } } } } $ret.='</tbody></table>'; if ($count>0) echo $ret; } } ?>
<script> jQuery(document).ready(function() { jQuery("body").on("click", ".setgift", function(e) { var ids=this.id; var myData = 'setgift='+ids; jQuery.ajax({ type: "POST", url: document.getElementById('siteurl').value+"index.php?<ссылка на файл, который обработает запрос>", dataType:"text", data:myData, success:function(response){ location.reload(); }, error:function (xhr, ajaxOptions, thrownError){alert(thrownError);} }); }); }); </script>
Необходимо внести изменения в модель корзины- чтобы подарки не меняли стоимость и кол-во, файл:
if ($jshopConfig->cart_basic_price_show){$this->products[$key]['basicprice'] = $product->getBasicPrice();} //корректировка подарка if ($this->products[$key]['price']>0) $this->products[$key]['quantity'] = $value; //корректировка подарка if ($this->products[$key]['price']==0 and $value>1) if ($value>1)$this->products[$key]['quantity']=1;
if ($this->products[$key]['quantity'] == 0 or $value==0){unset($this->products[$key]);} else if ($value==0) {unset($this->products[$key]);}
unset($product); //составляем массивы продуктов и подарков $productmass=array();$giftmass=array(); foreach ($this->products as $key_id=>$prod) { if ($prod['price']>0) $productmass[]=$prod['product_id']; else $giftmass[]=$prod['product_id']; } //проверка - должен ли быть подарок после удаления if (count($giftmass)>0) { foreach($giftmass as $gift) if (!in_array($gift,$productmass)) foreach($this->products as $key_id=>$prod) if ($this->products[$key_id]['product_id']==$gift) unset($this->products[$key_id]); } } } $this->loadPriceAndCountProducts(); $this->reloadRabatValue(); $this->saveToSession(); $dispatcher->trigger('onAfterRefreshProductInCart', array(&$quantity, &$this)); return 1; }
Остается файл, который обработает запрос при добавлении подарка:
//установка подарка if (isset($_POST['setgift']) and strlen($_POST['setgift'])) { $ids=$_POST['setgift']; require_once(JPATH_ROOT.DS.'components'.DS.'com_jshopping'.DS.'models'.DS.'cart.php'); require_once(JPATH_ROOT.DS.'components'.DS.'com_jshopping'.DS.'models'.DS.'tempcart.php'); $cart = new jshopCart(); $tempcart = new jshopTempCart(); $cart->load(); //добавляем подарок $db = JFactory::getDbo(); $db->setquery("select (select `name_ru-RU` from #__jshopping_manufacturers m where m.manufacturer_id=p.product_manufacturer_id) as manufacturer, vendor_id,product_weight,manufacturer_code,product_ean,delivery_times_id,image,(select tax_name from #__jshopping_taxes where tax_id=product_tax_id)as tax,product_tax_id,`name_ru-RU` as name, (select group_concat(category_id) from #__jshopping_products_to_categories c where c.product_id=p.product_id) as category_id from #__jshopping_products p where product_id='".$ids."' ");$product=$db->loadobject(); $temp_product['quantity'] = 1; $temp_product['product_id'] = $ids; $temp_product['category_id'] = $product->category_id; $temp_product['tax'] = $product->tax; $temp_product['tax_id'] = $product->product_tax_id; $temp_product['thumb_image'] = 'thumb_'.$product->image; $temp_product['delivery_times_id'] = $product->delivery_times_id; $temp_product['ean'] = $product->product_ean; $temp_product['manufacturer_code'] = $product->manufacturer_code; $temp_product['attributes'] = ''; $temp_product['attributes_value'] = array(); $temp_product['extra_fields'] = array(); $temp_product['weight'] = $product->product_weight; $temp_product['vendor_id'] = $product->vendor_id; $temp_product['files'] = ''; $temp_product['freeattributes'] =''; $temp_product['manufacturer'] = $product->manufacturer; $temp_product['price']=0; $temp_product['product_name']=$product->name.'(ПОДАРОК)'; $cart->products[] = $temp_product; $session = JFactory::getSession(); $session->set($cart->type_cart, serialize($cart)); exit(); }
Переменные будет созранять в сессии, для этого добавим код:
if (!isset($_SESSION['jsext_field_3'])) $_SESSION['jsext_field_3']=''; if (!isset($_SESSION['jsext_field_1'])) $_SESSION['jsext_field_1']=''; if (!isset($_SESSION['jsorder_id'])) $_SESSION['jsorder_id']='';
Далее добавим поля для ввода, у нас в примере была 6 способов доставки:
1 - Доставка курьером по г.Новосибисрку 2 - Доставка Почтой России. оптовая 3 - Доставка транспортной компанией 4 - Самовывоз из нашего офиса 5 - Доставка Почтой России. розничная 6 - Самовывоз из нашего офиса. розничная
Скрипт, котрый перебросит набранный текст и отправит его для внесения в сессию:
<script> jQuery(document).ready(function() { jQuery('body').on( "click",".changeshipping", function(){ var ids=this.id.split('_')[2]; var txt3=document.getElementById('shipping_text3_'+ids).value; var txt1=document.getElementById('shipping_text1_'+ids).value; txt3=txt3.replace("'",''').replace('`','`').replace('+','+').replace('+','='); txt1=txt1.replace("'",''').replace('`','`').replace('+','+').replace('+','='); if (document.getElementById('ext_field_3')!=null) document.getElementById('ext_field_3').value=txt3; if (document.getElementById('ext_field_1')!=null) document.getElementById('ext_field_1').value=txt1; jQuery('.to_ext3').hide(); if (ids!='4' && ids!='6')jQuery('#shipping_text3_'+ids).show(); //Полный адрес - только доставка с адресом if (ids=='3')jQuery('#shipping_text1_'+ids).show(); //Траспортная - только доставка траспортной }); jQuery('body').on( "change",".to_ext3", function(){ var ids=this.id.split('_')[2]; var txt3=document.getElementById('shipping_text3_'+ids).value; var txt1=document.getElementById('shipping_text1_'+ids).value; txt3=txt3.replace("'",''').replace('`','`').replace('+','+').replace('+','='); txt1=txt1.replace("'",''').replace('`','`').replace('+','+').replace('+','='); if (document.getElementById('ext_field_3')!=null) document.getElementById('ext_field_3').value=txt3; if (document.getElementById('ext_field_1')!=null) document.getElementById('ext_field_1').value=txt1; var myData='setextra='+ids+'&txt3='+txt3+'&txt1='+txt1; jQuery.ajax({ type: "POST", url: "index.php", dataType:"text", data:myData, success:function(response){}, error:function (xhr, ajaxOptions, thrownError){alert(thrownError);} }); }); }); </script>
Далее необходимперехват POST запроса и внесение в сессию, можно добавить на главной странице:
if (isset($_POST['setextra']) and strlen($_POST['setextra'])) { $ids=$_POST['setextra']; $txt1=$_POST['txt1']; $txt3=$_POST['txt3']; $_SESSION['jsext_field_3']=$txt3; $_SESSION['jsext_field_1']=$txt1; $_SESSION['jsorder_id']=$ids; exit(); }
Осталось только внести в заказ, редактируем файл:
components/com_jshopping/models/checkoutorder.php
public function orderDataSave(&$adv_user, &$post){ $jshopConfig = JSFactory::getConfig(); $dispatcher = JDispatcher::getInstance(); $session = JFactory::getSession(); $cart = $this->getCart(); $order = $this->createOrder($adv_user, $post); $dispatcher->trigger('onAfterCreateOrder', array(&$order, &$cart)); $this->couponFinished($adv_user->user_id, $order); $order->saveOrderItem($cart->products); $dispatcher->trigger('onAfterCreateOrderFull', array(&$order, &$cart)); $this->setEndOrderId($order->order_id); $order->saveOrderHistory(1, ''); $order->updateProductsInStock(1); $db = JFactory::getDbo(); if (isset($_SESSION['jsext_field_3']) and strlen($_SESSION['jsext_field_3'])>0) { //полный адрес $db->setquery("update #__jshopping_orders set ext_field_3='".$_SESSION['jsext_field_3']."',D_ext_field_3='".$_SESSION['jsext_field_3']."' where order_id='".$order->order_id."' "); $db->execute(); } if (isset($_SESSION['jsext_field_1']) and strlen($_SESSION['jsext_field_1'])>0) { //транспортная $db->setquery("update #__jshopping_orders set ext_field_1='".$_SESSION['jsext_field_1']."',d_ext_field_1='".$_SESSION['jsext_field_1']."' where order_id='".$order->order_id."' "); $db->execute(); } if ($jshopConfig->send_order_email && $order->order_created){$send = $this->sendOrderEmail($order->order_id);} return $order; }
После $order->saveOrderItem($cart->products); добавляем код:
$db->setquery("SELECT * FROM `#__jshopping_order_item` WHERE order_id='".$order->order_id."' ");$orditems=$db->loadobjectlist(); foreach($orditems as $orditem) if (trim($orditem->attributes)!='') { $attr = unserialize($orditem->attributes); $attrprice='';$needsave=0;$pricemass=array(); foreach($attr as $attritem=>$val ) { $db->setquery("select independent from #__jshopping_attr where attr_id='".$attritem."'");$independent=$db->loadresult(); if ($independent==1) { $db->setquery("select concat(price_mod,addprice) from #__jshopping_products_attr2 where attr_id='".$attritem."' and attr_value_id='".$val."' and product_id='".$orditem->product_id."' ");$attrprice=$db->loadresult(); if (isset($orditem->attrprice) and ($orditem->attrprice)!='') {$pricemass=json_decode($orditem->attrprice,true);} else {$needsave=1;} if (!isset($pricemass[$attritem.'-'.$val])) { $pricemass[$attritem.'-'.$val]=number_format($attrprice,2,'.',' '); $needsave=1; } } if ($needsave==1) { $massstr=json_encode($pricemass); $db->setquery("update #__jshopping_order_item set attrprice='".$massstr."' where order_item_id='".$orditem->order_item_id."' ");$db->execute(); } } }
Далее необходимо вывести эти данные в административной части, файл
<td class="atrrlist"> <?php $attr = unserialize($item->attributes); echo formatprice($item->product_item_price, $order->currency_code); if (isset($item->_ext_price_html)) print $item->_ext_price_html; $attrprice='';$needsave=0;$pricemass=array(); foreach($attr as $attritem=>$val ) { $db->setquery("select `name_ru-RU` from #__jshopping_attr where attr_id='".$attritem."'");$attrname=$db->loadresult(); $db->setquery("select independent from #__jshopping_attr where attr_id='".$attritem."'");$independent=$db->loadresult(); $db->setquery("select `name_ru-RU` from #__jshopping_attr_values where attr_id='".$attritem."' and value_id='".$val."' ");$attrval=$db->loadresult(); if ($independent==1) { $db->setquery("select concat(price_mod,addprice) from #__jshopping_products_attr2 where attr_id='".$attritem."' and attr_value_id='".$val."' and product_id='".$item->product_id."' ");$attrprice=$db->loadresult(); if (isset($item->attrprice) and ($item->attrprice)!='') {$pricemass=json_decode($item->attrprice,true);} else {$needsave=1;} if (!isset($pricemass[$attritem.'-'.$val])) { $pricemass[$attritem.'-'.$val]=number_format($attrprice,2,'.',' '); $needsave=1; } if ($attrprice>0) echo '<br><span class="attrid_'.$attritem.' valid_'.$val.'">'.$attrname.'</span> : '.$attrval.' цена '.$pricemass[$attritem.'-'.$val]; } if ($needsave==1) { $massstr=json_encode($pricemass); $db->setquery("update #__jshopping_order_item set attrprice='".$massstr."' where order_item_id='".$item->order_item_id."' ");$db->execute(); } } ?> </td>
Примерно на ~258 строке происходит проверка на ввод поисковой фразы, нам нужно добавить флаг "был ли поиск"
$is_searsh=0; if (!empty($this->keyword) and $this->keyword !== '' and $group === FALSE) { $is_searsh=1;
Далее в блоке фильтра по категории, добавляет условие нового флага - если введено поисковое слово то игнорируем категорию
if ($virtuemart_category_id > 0 and $is_searsh==0) { $joinCategory = TRUE; $categories = array(); VmModel::getModel('category')->GetTreeCatArray($categories, $virtuemart_category_id); $where[] = ' `pc`.`virtuemart_category_id` in (\'' . implode('\',\'',$categories).'\')'; } else
Дополнительно можно отсеять товар перед выводм, например вывести только уникальные названия, в этом же методе перед выводом результата:
//убираем дубликаты по названию if ($is_searsh==1 and count($product_ids)>0) { $db = JFactory::getDbo(); $db->setquery("select p.virtuemart_product_id as id,product_name as name from #__virtuemart_products p left join #__virtuemart_products_ru_ru as r on r.virtuemart_product_id=p.virtuemart_product_id where p.virtuemart_product_id in (".implode(',',$product_ids).") ");$lists=$db->loadobjectlist(); $product_ids=array(); $product_ids_name=array(); foreach($lists as $ll) { $is_new=1; foreach($product_ids_name as $nn) {if ($nn==$ll->name) $is_new=0;} if ($is_new==1) { $product_ids[]=$ll->id; $product_ids_name[]=$ll->name; } } } return $product_ids;
Но в этом методе не хватает защиты - нам необходимо проверить статус оплаты, до момента создания заказа и отправки письма, с корректировкой метод будет выглядеть так:
// Direct payment public function direactPayment() { $db = JFactory::getDbo(); $compo_params = JComponentHelper::getParams('com_splms'); $sber_ref = $compo_params->get('sber_ref',''); $user = JFactory::getUser(); // Load Lessons model jimport('joomla.application.component.model'); JModelLegacy::addIncludePath(JPATH_SITE . '/components/com_splms/models'); $model = JModelLegacy::getInstance('Payment', 'SplmsModel'); $cookie = JFactory::getApplication()->input->cookie; $orders_info = $cookie->get('splmsOrders', base64_encode(serialize(array()))); $orders_info = unserialize(base64_decode($orders_info)); if ($user-> guest) { JFactory::getApplication()->enqueueMessage(JText::_('COM_SPLMS_CART_LOGIN_TO_CHECKOUT'), 'warning'); } elseif (isset($orders_info) && is_array($orders_info)) { if (count($orders_info) and isset($_GET['orderId'])) { //проверка платежа $compliteorger=$_GET['orderId']; $compo_params = JComponentHelper::getParams('com_splms'); $sber_login = $compo_params->get('sber_login','login'); $sber_pass = $compo_params->get('sber_pass','pass'); $sberdebug = $compo_params->get('sberdebug','1'); $sber_token = $compo_params->get('sber_token',''); $sberauthtype = $compo_params->get('sberauthtype','0'); if ($sberauthtype==0) $authpass='token='.$sber_token; if ($sberauthtype==1) $authpass='userName='.$merchant['login'].'&password='.$merchant['password']; if ($sberdebug==1) $main_server = 'https://3dsec.sberbank.ru/payment/rest/register.do'; if ($sberdebug==0) $main_server = 'https://securepayments.sberbank.ru/payment/rest/'; //запрос статуса платежа на стороне банка $query_url='https://securepayments.sberbank.ru/payment/rest/getOrderStatus.do?language=ru&'.$authpass.'&orderId='.$compliteorger; $ch = curl_init() or die('Ошибка инициализации cURL'); //инициализируем протокол cURL //устанавливаем все необходимые данные curl_setopt($ch, CURLOPT_URL, $query_url); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); curl_setopt($ch, CURLOPT_USERAGENT, 'PHP Payment Gateway by Fuss (https://fussraider.ru)'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($ch) or die('Не удалось послать данные на сервер, повторите попытку. Error: ' . curl_error($ch)); $data_arr = json_decode($data, true); if (isset($data_arr['ErrorMessage']))$message=$data_arr['ErrorMessage'];else $message=''; if(isset($data_arr['ErrorCode']) and $data_arr['ErrorCode']=='0') { //создаем заказ $model->insertOrders($orders_info); //clear cookie $cookie->set('splmsOrders', null,time()-1); if (isset($user->email) && $user->email) {self::sendPurchasdeMail($user->email, $orders_info);} JFactory::getApplication()-> enqueueMessage(JText::_('COM_SPLMS_DIRECT_ORDER_SUBMITED'), 'success'); echo '<script>window.setTimeout(function(){location.href = "'.JURI::root().$sber_ref.'";}, 2000);</script>'; } else JFactory::getApplication()-> enqueueMessage(JText::_('Платеж не прошел, обратитесь к администратору<br>'.$message), 'warning'); } else { JFactory::getApplication()-> enqueueMessage(JText::_('COM_SPLMS_NO_ITEM_IN_CART'), 'warning'); //echo '<p>Корзина пуста</p>'; echo '<script>window.setTimeout(function(){location.href = "'.JURI::root().$sber_ref.'";}, 2000);</script>'; } } else { JFactory::getApplication()-> enqueueMessage(JText::_('COM_SPLMS_SOMETHING_WRONG'), 'warning'); //echo '<p>Ошибка</p>'; } }
JoomShopping - добавить в списке категорий кол-во товара
Список категорий можно расширить - указать кол-во товаров.
Для этого необходимо в запросе к БД добавить опрос товаров по категории, файл:
/components/com_jshopping/tables/category.php
В запросе к категориям добавляем запрос на кол-во товаров. В данном примере берется товар из текущей категории и один уровень дочерней, если у вас более одного уровня вложений категорий, необходимо рекурсивный опрос.
$query = "SELECT `".$lang->get('name')."` as name,`".$lang->get('description')."` as description,`".$lang->get('short_description')."` as short_description, category_id, category_publish, ordering, category_image, (select count(product_id) from #__jshopping_products_to_categories as cp where cp.product_id in (select product_id from #__jshopping_products where (product_quantity>0 or unlimited=1) and product_publish=1 and product_price>1 and image<>'' ) and cp.category_id in (select category_id from #__jshopping_categories as cd where cd.category_parent_id=c.category_id or cd.category_id=c.category_id) ) as aaa FROM `#__jshopping_categories` as c WHERE category_parent_id = '".$this->_db->escape($parentId)."' ".$add_where." ORDER BY ".$orderby." ".$ordering;
ЛИЦЕНЗИЯ НА ИСПОЛЬЗОВАНИЕ И ОГРАНИЧЕННАЯ ГАРАНТИЯ Это юридически обязательное соглашение. Устанавливая и/или используя программное обеспечение с данного сайта (далее Программное обеспечение), Вы соглашаетесь следовать условиям этого соглашения. КАК ЕСТЬ. Вы принимаете Программное обеспечение как есть, в его текущем состоянии, без любой подразумеваемой гарантии или особенностей. ПРЕДОСТАВЛЕНИЕ ЛИЦЕНЗИИ. Вам предоставляется неисключительное право использовать Программное обеспечение в соответствии с условиями, указанными в этом соглашении. Вы можете использовать Программное обеспечение на единственной установке Joomla!. УСТАНОВКА. Программное обеспечение должно только быть установлено на публично-доступном вебсайте. АВТОРСКОЕ ПРАВО И СОБСТВЕННОСТЬ. Это Программное обеспечение, включая его код, документацию, дистрибутив, структуру - исключительный продукт Radgura.ru, который сохраняет права собственности на Программное обеспечение, его копии и модификации. Также Radgura.ru сохраняет за собой авторское право на Программное обеспечение. КОПИИ. Вы можете сделать так много копий Программного обеспечения как хотите, пока Вы гарантируете, что Программное обеспечение используется только на одном вебсайте (установке Joomla). Вы не можете распространять копии Программного обеспечения другим. МОДИФИКАЦИЯ. Вы можете изменить составляющий исходный текст Программного обеспечения только для вашего собственного использования. Условия этого Лицензионного соглашения в этом случае будут не нарушены. Перепродажа или распространение любой модификации не позволяется без письменного разрешения от Radgura.ru. ПЕРЕДАЧА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ. Вы не можете передавать Программное обеспечение в третьи руки без письменного разрешения на это от Radgura.ru. Ни в коем случае Вы не можете передавать, назначать, арендовать, продавать Программное обеспечение в том числе. Вы несете полную ответственность за переданные Вам в пользование копии Программного обеспечения, и обязаны принять все меры для того, чтобы Программное обеспечение не попало в третьи руки. ЗАКЛЮЧИТЕЛЬНЫЕ ПОЛОЖЕНИЯ. Это Соглашение действует весь период использования Программного обеспечения пока не будет прервано. Это Соглашение прервется автоматически без уведомления от Radgura.ru, если Вы будете не в состоянии выполнить какое-либо условие этого Соглашения. После завершения Вы должны прекратить использование всех копий Программного обеспечения, включая измененные копии, если таковые имеются. ИСКЛЮЧЕННЫЕ ГАРАНТИИ. Radgura.ru не несет ответственности ни за какие убытки, являющиеся результатом любой причины, даже если Radgura.ru сообщили о возможности таких убытков. Radgura.ru ни в коем случае не будет нести ответственности за любые убытки, большие чем уплаченная Вами стоимость Программного обеспечения. Любые гарантии ограничены в продолжительности 30 днями после даты оплаты Программного обеспечения. ПРАВО ОТКАЗА. Мы оставляем за собой право по своему усмотрению, прекратить предоставление услуг и реализацию предлагаемых товаров, а также изменять/закрывать доступ к ранее приобретенным товарам на нашем сайте, в случае нарушения положений, изложенных в данном лицензионном соглашении, а также случая повлекших нарушение авторского права или содействия в вопросе нарушения авторских прав, на представленное на данном сайте Программное обеспечение. ЕСЛИ ВЫ НЕ СОГЛАШАЕТЕСЬ НА УСЛОВИЯ ЭТОГО СОГЛАШЕНИЯ, НЕ ИСПОЛЬЗУЙТЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ.
JoomShopping - OneStepCheckout изменение стоимости доставки от кол-ва товаров
Стандартный механизм JoomShopping не умеет делать сложный расчет доставки, необходимо вносить изменения.
Поставлена задача:
1. Добавлять 200р к доставке, если товаров больше одного, при этом есть исключения по товару.
Сначала вводим признак, по которому будем исключать товар, для этого создаем характеристику.Необходимо поставить эту характеристику всем товарам, которые не будут добавлять 200р к доставке.
Далее нам необходимо понять в какое поле она будет выгружаться, у нас получилось поле #__jshopping_products.extra_field_3, ID характеристики 4.
Следующий шаг расчета стоимости доставки
Карточки товара из корзины JoomShopping хранятся в сессии, для обновлении цены нам необходимо "на лету" изменить данные, открываем файл:
Это шаблон корзины, реализуем подсчет кол-во товара:
<tbody> <?php $i=1; $countprod = count($this->products);$qunt=0; foreach ($this->products as $key_id=>$prod) { $db->setquery("select extra_field_3 from #__jshopping_products where product_id='".$prod['product_id']."' ");$ext=$db->loadresult();//поле скрыто, получаем значение из БД if ($ext!=4) $qunt=$qunt+$prod['quantity']; ?> <tr class="jshop_prod_cart" >
И нужно переопределить вывод суммы:
$session = JFactory::getSession(); $price = $session->get("jshop_price_shipping"); //если товаров несколько то к каждой позиции кроме первой добавляем 200р if ($price>0) { $quntprice=0; if ($qunt>1) $quntprice=($qunt-1)*200; else $quntprice=0; $this->summ_delivery=getRoundPriceProduct(floatval($price+$quntprice)); } if (isset($this->summ_delivery)){ ?> <tr> <td class="name"> <?php echo JText::_('JSHOP_ONESTEPCHECKOUT_SHIPPING_PRICE') ?> </td> <td class="value SHIPPING_PRICE"> <?php echo formatprice($this->summ_delivery) ?> <?php echo $this->_tmp_ext_shipping?> </td> </tr> <?php } ?>
if ($jshopConfig->send_order_email && $order->order_created){ $send = $this->sendOrderEmail($order->order_id); } //обновляем стоимость доставки, исключаем кол-во товара по характеристике if ($order->order_shipping>0) { $db = JFactory::getDbo(); $db->setquery("SELECT SUM(`product_quantity`) FROM `#__jshopping_order_item` WHERE order_id='".$order->order_id."' and product_id not in (select product_id from #__jshopping_products where extra_field_3=4)");$qunt=$db->loadresult(); $quntprice=0; if ($qunt>1) { $quntprice=($qunt-1)*200; $order_shipping=getRoundPriceProduct(floatval($order->order_shipping+$quntprice)); $db->setquery("update `#__jshopping_orders` set order_shipping='".$order_shipping."' WHERE order_id='".$order->order_id."' ");$db->execute(); $db->setquery("update `#__jshopping_orders` set order_total=order_shipping+order_subtotal+order_payment WHERE order_id='".$order->order_id."' ");$db->execute(); } }
2.Стоимость доставки индивидуальна для каждого товара. Доставка рассчитывается: 100% от первого товара, 50% от второго. Стоимость доставки брать от наибольшей.
$first=0;$second=0; $db->setquery("select yan_local_delivery_cost as cost from #__jshopping_products where product_id in (select product_id FROM `#__jshopping_order_item` WHERE order_id='".$order->order_id."' and product_id not in (select product_id from #__jshopping_products where extra_field_3=4)) order by yan_local_delivery_cost desc limit 2");$delcostlist=$db->loadobjectlist(); if (isset($delcostlist[0]->cost)) { $first=$delcostlist[0]->cost; if ($prod['quantity']>1)$second=(int)($delcostlist[0]->cost/2); else if (isset($delcostlist[1]->cost)) $second=$delcostlist[1]->cost; } $db->setquery("update `#__jshopping_orders` set order_shipping='".($first+$second)."' WHERE order_id='".$order->order_id."' ");$db->execute(); $db->setquery("update `#__jshopping_orders` set order_total=order_shipping+order_subtotal+order_payment+order_package WHERE order_id='".$order->order_id."' ");$db->execute(); return $order;
function addTitleHead($is_spec=0){ $jshopConfig = JSFactory::getConfig(); $vendorinfo = $this->_vendorinfo; if (file_exists($jshopConfig->path.'images/'.$this->img_header)){ $this->Image($jshopConfig->path.'images/'.$this->img_header,1,1,$jshopConfig->pdf_header_width,$jshopConfig->pdf_header_height); } if (file_exists($jshopConfig->path.'images/'.$this->img_footer)){ $this->Image($jshopConfig->path.'images/'.$this->img_footer,1,265,$jshopConfig->pdf_footer_width,$jshopConfig->pdf_footer_height); } $this->SetFont('freesans','',8); $this->SetXY(115,12); $this->SetTextColor($this->pdfcolors[2][0], $this->pdfcolors[2][1], $this->pdfcolors[2][2]); $_vendor_info = array(); $_vendor_info[] = "Компания ООО ТК-СИТИ"; //Выводим название нащей организации, вместо текста можно вставить $vendorinfo->firma , тогда название возьмется из инфы о магазине $_vendor_info[] = "Адрес компании: $vendorinfo->zip Россия, г.Москва"; //Выводим почтовый адрес компании $_vendor_info[] = ", $vendorinfo->adress"; //Выводим город и улицу $_vendor_info[] = "Интернет-сайт: $vendorinfo->url, E-mail: Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.;; //Вводим интернет-сайт организации и E-mail $_vendor_info[] = "Телефон/Факс: $vendorinfo->phone $vendorinfo->fax"; //Вводим телефон и факс $str_vendor_info = implode("\n",$_vendor_info); $this->MultiCell(90, 1, $str_vendor_info, 0, 'R'); //Ширина выводимых данных $this->SetTextColor($this->pdfcolors[11][0], $this->pdfcolors[0][1], $this->pdfcolors[0][2]); }
Вы можете заменить значение строк или добавить свои
$db->setQuery("select category_parent_id,category_id as id,`name_ru-RU` as name,(select count(*) from #__jshopping_products_to_categories as ss where ss.category_id=c.category_id ) as cc from #__jshopping_categories as c where category_publish=1 order by `name_ru-RU`"); $item_ops = $db->loadObjectList();
Функция обхода категорий, создание опций для <select>:
function getrecopt($item_ops,$lvlstr,$parentid,$filter) { $ret=''; foreach ($item_ops as $item_op) if ($item_op->category_parent_id==$parentid) { $ret.='<option value="'.$item_op->id.'" '.(($filter==$item_op->id)?'selected="selected"':'').'>'.$lvlstr.$item_op->name.' ('.$item_op->cc.')</option>'; $ret.=getrecopt($item_ops,$lvlstr.'--',$item_op->id,$filter); } return $ret; }
1.Пользователь перетаскивает строку, зажав элемент <i class="icon-move"></i>
2.После завершения, скрипт анализирует позицию с которой был взял элемент и позицию на которую он перемещен, далее по элементам <input type="hidden" id="imageindex_1" value="2"> в атрибуте value получаем ID записи
3.Делаем запрос в БД на изменение позиции(ordering)
Скрипт выполняющий поиск ID старой и новой позиции:
if (isset($_POST['changeord']) and strlen($_POST['changeord'])) { $target_id=trim($_POST['target_id']); $self_id=trim($_POST['self_id']); $db = JFactory::getDbo(); $db->setquery("select ordering from #__table where id='".$target_id."'");$target_id_ord=$db->loadresult(); $db->setquery("select ordering from #__table where id='".$self_id."'");$self_id_ord=$db->loadresult(); $db->setquery("update #__table set ordering='".$self_id_ord."' where id='".$target_id."'");$db->execute(); $db->setquery("update #__table set ordering='".$target_id_ord."' where id='".$self_id."'");$db->execute(); exit(); }
$db = JFactory::getDbo(); $db->setquery("Select atr2.*,(select `name_ru-RU` from #__jshopping_attr_values where value_id=atr2.attr_value_id) as name from #__jshopping_products_attr2 atr2 where attr_id='".$attribut->attr_id."' and product_id='".$this->product->product_id."' ");$attrmass=$db->loadobjectlist(); if (count($attrmass)!=2) echo $attribut->selects;//кол-во не 2 else if (($attrmass[0]->addprice<>0 and $attrmass[0]>addprice<>$this->product->getPriceCalculate()) and ($attrmass[1]->addprice<>0 and $attrmass[1]->addprice<>$this->product->getPriceCalculate())) echo $attribut->selects;//сумма обоих больше 0 else { if ($attrmass[0]->addprice==0 or $attrmass[0]->addprice==$this->product->getPriceCalculate()) { $name=$attrmass[1]->name; $null_valid=$attrmass[0]->attr_value_id; $notnull_valid=$attrmass[1]->attr_value_id; $null_atrid=$attrmass[0]->attr_id; $notnull_atrid=$attrmass[1]->attr_id; } else { $name=$attrmass[0]->name; $null_valid=$attrmass[1]->attr_value_id; $notnull_valid=$attrmass[0]->attr_value_id; $null_atrid=$attrmass[1]->attr_id; $notnull_atrid=$attrmass[0]->attr_id; } echo '<div style="background:yellow;display:none;">'.$attribut->selects.'</div>';//выводим стандартную форму с опциями, но прячим ее echo '<span class="input_type_radio">'; echo '<input type="checkbox" style="height:20px;width:20px;" onclick="if(this.checked){jQuery('."'#jshop_attr_id".$attribut->attr_id.$notnull_valid."'".').trigger('."'click'".');}else{jQuery('."'#jshop_attr_id".$attribut->attr_id.$null_valid."'".').trigger('."'click'".');}" name="checkattr'.$attribut->attr_id.'" id="checkattr'.$attribut->attr_id.'"><label style="cursor:pointer;margin-left:10px;top: -5px;position:relative;white-space: normal;width: 200px;" class="cssm-label" for="checkattr'.$attribut->attr_id.'">'.$name.'</label>'; echo '</span>'; }
1.Некорректно вычисляется кол-во товара в партии на странице товара VM3?
Причина: Родной скрипт не готов обрабатывать атрибуты объекта, поэтому кол-во товаров некорректно высчитывается в случае, когда нужно изменить партию в шаге больше 1.
Исправление в VM3 в файле:
components\com_virtuemart\assets\js\vmprices.js
Необходимо исправить ссылку на атрибут и добавить условие обработки кол-ва - проверить точное соотношение шага и текущего кол-ва, если кол-во больше, то необходимо убрать излишек.
Virtuemart.incrQuantity = (function(event) { var rParent = jQuery(this).parent().parent(); quantity = rParent.find('input[name="quantity[]"]'); virtuemart_product_id = rParent.find('input[name="virtuemart_product_id[]"]').val(); Ste = parseInt(quantity.attr("data-step")); if (isNaN(Ste)) Ste = 1; Qtt = parseInt(quantity.val()); if (!isNaN(Qtt)) { var nQtt=Qtt + Ste; var rQtt=(Math.ceil(Qtt/Ste)); if ((nQtt-(rQtt*Ste))>0) nQtt=rQtt*Ste+Ste; quantity.val(nQtt); maxQtt = parseInt(quantity.attr("max")); if(!isNaN(maxQtt) && quantity.val()>maxQtt){ quantity.val(maxQtt); } Virtuemart.setproducttype(event.data.cart,virtuemart_product_id); } });
Virtuemart.decrQuantity = (function(event) { var rParent = jQuery(this).parent().parent(); var quantity = rParent.find('input[name="quantity[]"]'); var virtuemart_product_id = rParent.find('input[name="virtuemart_product_id[]"]').val(); var Ste = parseInt(quantity.attr("data-step")); if (isNaN(Ste)) Ste = 1; var minQtt = parseInt(quantity.attr("data-init")); if (isNaN(minQtt)) minQtt = 1; var Qtt = parseInt(quantity.val());if (!isNaN(Qtt) && Qtt>Ste) { var nQtt=Qtt - Ste; var rQtt=(Math.ceil(Qtt/Ste)); if ((nQtt-(rQtt*Ste))>0) nQtt=rQtt*Ste-Ste; quantity.val(nQtt); if(!isNaN(minQtt) && quantity.val()<minQtt){ quantity.val(minQtt); } } else quantity.val(minQtt); Virtuemart.setproducttype(event.data.cart,virtuemart_product_id); });
2.В миниатюре корзины SJ Mod miniCart не работает добавление товаров с шагами?
В данном модуле не было рассмотрена такая ситуация, поэтому нужно добавить вычисление кол-во с шагами.
/*-- process when click quantity control and change value input quantity --*/ $('.quantity-control', $_prod).each(function () { $(this).children().click(function () { var Qtt = parseInt($_quantity.val()); var Qtt = parseInt($_quantity.val()); var Ste = parseInt($_quantity.attr("data-step")); if (isNaN(Ste)) Ste = 1; if ($(this).is('.quantity-plus')) { var nQtt=Qtt + Ste; var rQtt=(Math.ceil(Qtt/Ste)); if ((nQtt-(rQtt*Ste))>0) nQtt=rQtt*Ste+Ste; $_quantity.val(nQtt); } else { if (!isNaN(Qtt) && Qtt > 1) { var nQtt=Qtt - Ste; var rQtt=(Math.ceil(Qtt/Ste)); if ((nQtt-(rQtt*Ste))>0) nQtt=rQtt*Ste-Ste; if (nQtt<Ste) nQtt=Ste; $_quantity.val(nQtt); } else { $_quantity.val(Ste); } } if ($_quantity.val()==0) $_quantity.val(Ste); return false; }); })
Joomla 3 - первоначальная настройка и важные моменты
В ходе работы с данной CMS были выработаны несколько основных подходов:
1.Отключайте tooltips, если в них нет явной необходимости.
Это связано с тем, что часто возникает ошибка выполнения jQuery запроса, который пытается обратиться к функции tooltips, но она еще не успела загрузиться, в итоге перестают работать все пользовательские функции реализованные на JQuery.
2.Блокируйте или удаляйте стандартные контакты (Компоненты -> Контакты) если в них нет необходимости, но если вы ими пользуетесь, то ставьте captcha.
Данным функционалом могут воспользоваться злоумышлиники и рассылать спам через ваш сайт, для этого достаточно выполнить http запрос к вашему сайту и опубликованному контакту, данный запрос требует указать сущесвующий ID контакта /index.php?option=com_contact&view=contact&id=1
3.Не публикуйте почтовый адрес в открытом виде, потому что злоумышлинники включат его в спам рассылки.
VM3 права для редактирования заказа не администратору сайта
В компоненте VirtueMart 3 реализован собственный класс для построения административного меню,который игнорирует(переписывает) стандарные права Joomla.
Если вы хотите дать права на редактирование заказов менеджеру, то этот менеджер должен быть с правами супер администратора, иначе у него просто не будет доступен нужный пункт меню.
Права на области VM (модули) задаются в таблице #__virtuemart_modules, варианты none,admin,storeadmin,shopper,demo
На дальше этот параметр в стандартной версии VM3 не распространяется, скорее всего нужно устанавливать дополнительный плагин или компонент, это можно обойти и открыть меню всем, у кого есть доступ в админ панель.
Данная функция позволит создать миниатюра, удобно для представления в администивной части и галереи пользователя, нужно указать путь до оригинала и путь до будующей миниатюры и ее размер(можно ограничиться только один показателем высотой или шириной), картинка будет уменьшина пропорционально:
function create_thumb($image,$thumbimage,$h_o = false,$w_o = false) { if (($w_o < 0) || ($h_o < 0)){return false;} list($w_i, $h_i, $type) = getimagesize($image); // Получаем размеры и тип изображения (число) $types = array("", "gif", "jpeg", "png"); // Массив с типами изображений $ext = $types[$type]; // Зная "числовой" тип изображения, узнаём название типа if ($ext) { $func = 'imagecreatefrom'.$ext; // Получаем название функции, соответствующую типу, для создания изображения $img_i = $func($image); // Создаём дескриптор для работы с исходным изображением } else {return false;} /* Если указать только 1 параметр, то второй подстроится пропорционально */ if (!$h_o) $h_o = $w_o / ($w_i / $h_i); if (!$w_o) $w_o = $h_o / ($h_i / $w_i); $img_o = imagecreatetruecolor($w_o, $h_o); // Создаём дескриптор для выходного изображения imagecopyresampled($img_o, $img_i, 0, 0, 0, 0, $w_o, $h_o, $w_i, $h_i); // Переносим изображение из исходного в выходное, масштабируя его $func = 'image'.$ext; // Получаем функция для сохранения результата return $func($img_o, $thumbimage); // Сохраняем изображение в тот же файл, что и исходное, возвращая результат этой операции }
Потому что был написан до изобретения авторского права:
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Решение этой проблемы состоит в нескольких вариантах:
1.Статусы
Необходимо корректно настроить статусы, при которых будет отправляться письмо
Вкладка "Настройки" - "Электронная почта"
Статус заказа по умолчанию для создания выписанного счета - указать статус для нового заказа, должен быть "Pennding"
Статус заказа по умолчанию для отправки эл.письма покупателю - также указать "Pennding" + добавить другие интересующие статусы
Статус заказа по умолчанию для отправки эл.письма продавцу- также указать "Pennding" + добавить другие интересующие статусы
Можно также указать принудительно статусы, которые будут формировать письмо. Необходимо отредактировать файл administrator/components/com_virtuemart/models/orders.php
// Send the email
//$res = shopFunctionsF::renderMail('invoice', $order['details']['BT']->email, $vars, null,$vars['doVendor'],$this->useDefaultEmailOrderStatus);
$sendMail = false;
if(!$this->useDefaultEmailOrderStatus and isset($vars['newOrderData']['customer_notified']) and $vars['newOrderData']['customer_notified']==1){
$sendMail = true;
} else {
$orderstatusForShopperEmail = VmConfig::get('email_os_s',array('U','C','S','R','X'));
if(!is_array($orderstatusForShopperEmail)) $orderstatusForShopperEmail = array($orderstatusForShopperEmail);
$orderstatusForShopperEmail[] = 'P';//TODO: Фикс для того чтобы письма отправлялись покупателю сразу после заказа
if ( in_array((string) $vars['orderDetails']['details']['BT']->order_status,$orderstatusForShopperEmail) ){
$sendMail = true;
vmdebug('renderMail by default orderstati');
}
}
2.Проблемы с доставщиком почты
Рекомендуется в настройках указать отправку через smtp
Если же вы используете phpmailer, необходимо в файле libraries/vendor/phpmailer/phpmailer/class.phpmailer.php исправить код:
private function mailPassthru($to, $subject, $body, $header='', $params='') { //Check overloading of mail function to avoid double-encoding if (ini_get('mbstring.func_overload') & 1) { $subject = $this->secureHeader($subject); } else { $subject = $this->encodeHeader($this->secureHeader($subject)); } //Can't use additional_parameters in safe_mode //@linkhttp://php.net/manual/en/function.mail.php if (ini_get('safe_mode') or !$this->UseSendmailOptions) { $result = @mail($to, $subject, $body, $header); } else
$datawhow=1;//счетчик элементов foreach (база элементов) { .... if ($datashow<=($tabnav*$userlistcount) and $datashow>(($tabnav-1)*$userlistcount)) { .... //вывод элементов .... } $datashow++; }
Вариант №2 - использование $_GET и построение двойным списком
Переменные:
$posts_count = count($res->posts);//итого кол-во материалов
$posts_per_page = 6;//материалов на странице по умолчанию
if($_GET['per_page']){$posts_per_page = $_GET['per_page'];}//материалов на странице получаем из ссылки
$count_pages = round($posts_count / $posts_per_page);//кол-во страниц, округляем до целого
if (($count_pages*$posts_per_page)<$posts_count) $count_pages++;//ситуация: кол-во материалов не равно бьется с $posts_per_page
На веб-сайте будет отображен адрес Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра. со ссылкой mailto.
Адрес без ссылки
Если вы хотите просто вывести замаскированный адрес электронной почты, то используйте следующий код:
На веб-сайте будет отображен адрес Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра. без ссылки mailto.
Адрес, отличный от адреса в ссылке
Если вы хотите вывести замаскированный адрес электронной почты, ссылка которого ведет на другой адрес, используйте следующий код:
На веб-сайте будет отображена фраза Свяжитесь с нами, при этом ссылка mailto будет вести на адрес Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра..
Использовать скрипт
Необходимо будет разместить элемент с ID=emailtopstr, в который после отрисовки старницы будет добавлен адрес
<p>По всем вопросам : <span id="emailtopstr"></span></p> <script language="JavaScript"> var login = 'admin'; var server = 'radgura.ru'; var email = login+'@'+server; document.getElementById('emailtopstr').innerHTML=email; </script>
Параметры шаблона из файла, минуя Joomla framework:
// Get params.ini relative to the current file location (use your own relative path here) $paramsFile=dirname(__FILE__).'/../../params.ini'; // Only continue if the file exists if(file_exists($paramsFile)){ // Get contents from params.ini file $iniString=file_get_contents($paramsFile); // Escape double quotes in values and then double-quote all values (because Joomla doesn't do that for us..) $iniQuoted=preg_replace('/=(.*)\\n/',"=\"$1\"\n",addcslashes($iniString,'"')); // Parse the ini string to an associative array $iniParsed= parse_ini_string($iniQuoted); }else{ $iniParsed=''; } // Set params to obtained values or empty array $params=(!empty($iniParsed)) ? $iniParsed:array(); // Get param value from array $param=$params['paramName'];
В компоненте k2_store за обновление цены отвечает плагин, поэтому если вы решили менять цену не на странице редактирования материала, то обязательно нужно обновлять поле plugins в таблице #__k2_items:
$db->setQuery("select plugins from #__k2_items where id='".$ids."' "); $plugins=$db->loadresult(); if (trim($plugins)!=''){ $pluginsstr=(array)json_decode($plugins, true); $pluginsstr['k2storeitem_price']=$price; $pluginsstr['k2storespecial_price']=$sprice; $plugins=json_encode($pluginsstr,true); $db->setQuery("update #__k2_items set plugins='".$plugins."' where id='".$ids."' "); $db->execute(); } else { $plugins='{"k2storeitem_enabled":"1","k2storeitem_sku":"","k2storeitem_price":"0.00000","k2storespecial_price":"0.00000","k2storeitem_tax":"0","k2storeitem_shipping":"0","k2storeitem_metrics":{"item_length":"0.00000000","item_width":"0.00000000","item_height":"0.00000000","item_length_class_id":"0","item_weight":"0.00000000","item_weight_class_id":"0"},"k2storeitem_cart_text":"","k2StatisticHitscheck_item":"1"}'; $pluginsstr=(array)json_decode($plugins, true); $pluginsstr['k2storeitem_price']=$price; $pluginsstr['k2storespecial_price']=$sprice; $plugins=json_encode($pluginsstr,true); $db->setQuery("update #__k2_items set plugins='".$plugins."' where id='".$ids."' "); $db->execute(); }
Если вам необходимо прочитать путь до изображения, которое загружено в материал, поможет код:
$db->setQuery("select images from #__content where id='ID' "); $resimage=$db->loadresult(); $img=(array)json_decode($resimage, true);
Результатом будет массив, изображение можно найти по ключу "image_intro" $foto=$img['image_intro'];
Для записи, после изменения, нужно также получить массив из БД и обновить элемент с ключом "image_intro", далее преоброзовать его в строку:
$db->setQuery("select images from #__content where id='ID"); $resimage=$db->loadresult(); $img=(array)json_decode($resimage, true); $img['image_intro']=$foto;//обновление изображения $imgstr=json_encode($img,true); $db->setQuery("update #__content set ``images`='".$imgstr."' where id='ID'"); $db->execute();
$user = JFactory::getUser(); $is_opt=!$user->guest; ..... $conn=false; foreach($this->shipping_methods as $shipping){ if ($is_opt!='1' and in_array($shipping->sh_pr_method_id,array(1,3,5))) $conn=true;//розница if ($is_opt=='1' and in_array($shipping->sh_pr_method_id,array(2,3,4))) $conn=true;//оптовые if ($conn==true){ .... }
Ищем кнопку с id="confirmbtn_button" и ниже размещаем код
<p><small>Нажимая на кнопку «Оформить заказ», я соглашаюсь с условиями <a href="/<ссылка на договор-оферту>/" target="_blank"><small>Публичной оферты</small></a> и на обработку моих <a target="_blank" href="/<ссылка на согласние на обработку ПД>/"><small>персональных данных</small></a></small></p>
2.K2_store 3.x.x
В каждом плагине оплаты разместите текст в в файле /tmpl/prepayment.php в элементе form
<p><small>Нажимая на кнопку «Завершить заказ», я соглашаюсь с условиями <a href="/<ссылка на договор-оферту>/" target="_blank"><small>Публичной оферты</small></a> и на обработку моих <a target="_blank" href="/<ссылка на согласние на обработку ПД>/"><small>персональных данных</small></a></small></p>
3.JoomShoping - использовать встроенный механизм опций
А)Включаем опцию "Заявление о конфиденциальности" в "Настройки-заказ".
Б)В "настройки - статический текст" добавляем нужный текст текст "Заявление о конфиденциальности"
Г)В "Настройки - поля регистрации" включаем и делаем обязательным "Заявление о конфиденциальности"
Д)Через языковые константы изменить "Заявление о конфиденциальности" на "Согласие на обработку персональных данных"
<form class="jb_form"></form><div class="pd_do" style="padding: 5px;background: rgba(255, 255, 255, 0.52);"><div class="pd_po"><p><small>Нажимая на кнопку «Оформить заказ», я соглашаюсь с условиями <a href="/do" target="_blank"><small>Публичной оферты</small></a> и на обработку моих <a target="_blank" href="/pd"><small>персональных данных</small></a></small></p></div></div><div class="jb_success">
5.AcyMaling - модуль "Подписаться на рассылку"
Редактируем файл:
/modules/mod_acymailing/tmpl/default.php
Вставляем код перед </form>:
<p style="text-align:center;"><small>Нажимая на кнопку «Завершить заказ», я соглашаюсь с условиями <a href="/<ссылка на договор-оферту>/" target="_blank"><small>Публичной оферты</small></a> и на обработку моих <a target="_blank" href="/<ссылка на согласние на обработку ПД>/"><small>персональных данных</small></a></small></p>
В блоке "jQuery.each(data.products, function(id, product) {" необходимо подсчитать каждый элемент и умножить на кол-во, а также суммировать по всем элементам, чтобы после блока вывести:
...
var q=document.getElementById('quantity_'+id).value; var w=document.getElementById('product_weight_'+id).value; var p=document.getElementById('product_packaging_'+id).value;
...
if (jQuery('#subtotal_weight_'+id)) { jQuery('#subtotal_weight_'+id).html(w_t+' кг.'); } if (jQuery('#subtotal_packagingt_'+id)) { jQuery('#subtotal_packagingt_'+id).html(p_t+' м3'); }
....
Вывод суммы хар-к по всем товарам:
if (jQuery('#w_total')) {jQuery('#w_total').html(w_total+' кг.');} if (jQuery('#p_total')) {jQuery('#p_total').html(p_total+' м3');}
VirtueMart onepage Generic -автоматическое обновление цены при скидке на кол-во товара
В одностраничном плагине корзины не учитывается изменение цены на товар при увеличении его кол-ва.
Цену товара в VM можно настроить на группу или кол-во, при этом на странице корзины цена обновить только при полном обновлении сраницы, при изменении кол-ва цена товара не измениться.
Для начала необходимо подготовить переменную, файл:
/cart/ajaxprice.php
Необходимо добавить цену товара в строки с массивом $price_values["products"][$id][....]
На странице карточки добавить идентификатор, для изменения цены
Файл
/cart/tmp/default_left.php
Код :
<div class="opg-text-primary opg-hidden-small opg-text-bold opg-float-right opg-width-large-1-6 opg-width-small-2-6 opg-width-2-6 opg-text-left-small"> <div class="spacer" id="towprice_<?php echo $cartitemid?>"> <?php echo $this->currencyDisplay->createPriceDiv('salesPrice','', $this->cart->pricesUnformatted[$pkey],true,false,1); //No quantity or you must use product_final_price ?> <?php //echo $this->currencyDisplay->createPriceDiv('basePriceVariant','', $this->cart->pricesUnformatted[$pkey],false); ?> </div> </div>
осталось настроить скрипт автоподсчета, файл:
onepage.js
Необходимо доработать функцию:
function update_prices()
В функции function update_prices() добавить строку для замены текста в элементе с ценой:
if (jQuery('#subtotal_with_tax_'+id)) { jQuery('#subtotal_with_tax_'+id).html(data.products[id].subtotal_with_tax); } if (jQuery('#towprice_'+id)) { jQuery('#towprice_'+id).html(data.products[id].subtotal_with_tax); }
Взлом сайта Joomla - добавление кода для загрузки файлов
Столкнулся с изменением файлов на сайтах CSM Joomla, данные вписываются в базовые компоненты и библиотеку, злоумышленник делает загрузку файлов. профиклактика - заблокировать изменение этих файлов.
У k2 store для обновления цены и опций используется плагин и этот способ также гарантирует сохранность данных. Параметры товара, которые отображаются на форме администратора - это не данных из базы, а данные плагина для этого материала.
Такой подход дает гарантию, что данные будут изменены только фирменным плагином, но если вы используете другие компоненты, которые меняют параметры товара через базу, то нужно вносить поправки в параметры плагина или внести изменения в сам плагин, иначе при редактировании материала вы сбросите стоимость товара или опций.
Как актуализировать данные ?
Самый простой способ - изменить отображение параметров в плагине, вывести на форму данные из базы.
Для этого нужно редактировать файл
/plugins/k2/k2store/k2store.php
Начиная с 149 строки, внести изменение - прочитать параметры и заменить значения в массиве:
Для интернет магазинов есть потребность показать ассортимент товаров, один из способов -это отобразить, что покупают другие люди с этим товаром(состав чека).
У компонента К2 есть массив RelatedItems, но по умолчанию он не связан с K2Store, чтобы это исправить нужно отредактировать файл
components/com_k2/models/itemlist.php
В функцию function getRelatedItems($itemID, $tags, $params) необходимо вставить запрос, который посмотрит с чем продают ID этого товара и выведит 3 позиции из последних чеков
$query = "select distinct product_id from #__k2store_orderitems where order_id in (select order_id from #__k2store_orderitems where product_id={$itemID} order by modified_date desc ) and product_id<>{$itemID} limit 3"
K2 другие материалы этой категории - добавить элементы
По умолчанию К2 выводит только следующий и предыдущий материал в этой категории. Для интернет магазина понадобилось вывести 4 товара из одной категории.
<script> jQuery('document').ready(function(){ jQuery('#modal').modal("false"); }); function change_img(imgs) { document.getElementById('modal_img').src=imgs; } </script>
Рассмотрим на примере - необходимо вызывать модальное окно для просмотра назначенного изображения материала К2. Нам необходимо добавить функцию обновления ссылки на изображение по щелчку:
<script> function change_img(imgs) { document.getElementById('modal_img').src=imgs; } </script>
if(isset($_POST["recordToEx"])){ $idToUpd = str_replace('-','',filter_var($_POST["recordToEx"],FILTER_SANITIZE_NUMBER_INT)); if (isset($_POST["quant"])) $quant = filter_var($_POST["quant"],FILTER_SANITIZE_STRING); else $quant=''; if (isset($_POST["order"]))$order = filter_var($_POST["order"],FILTER_SANITIZE_STRING); else $order=''; //обновляем кол-во if (trim($quant) != '' and trim($order) != '') { $db = JFactory::getDbo(); $query =htmlspecialchars("update #__k2store_orderitems set orderitem_quantity ='".$quant."' where orderitem_id='".$idToUpd."'"); $db->setQuery($query); if(!$db->query()) { header('HTTP/1.1 500 '.JText::_("Ошибка ID = '".$idToUpd."' '".$db->stderr())); exit(); } } //выводим сумму позиции после обновления $query =htmlspecialchars("update #__k2store_orderitems set orderitem_final_price = (orderitem_price+ orderitem_attributes_price)*orderitem_quantity where orderitem_id='".$idToUpd."'"); $db->setQuery($query); if(!$db->query()) { header('HTTP/1.1 500 '.JText::_("Ошибка ID = '".$idToUpd."' '".$db->stderr())); exit(); } $query =htmlspecialchars("(select ROUND(sum(orderitem_final_price)) as total_summ,(select ROUND(orderitem_final_price) from #__k2store_orderitems where orderitem_id='".$idToUpd."') as summ_item from #__k2store_orderitems where order_id = (select order_id from #__k2store_orderitems where orderitem_id='".$idToUpd."'))"); $db->setQuery($query); $res = $db->loadObject(); echo str_replace('.00000','.00 руб.',$res->summ_item).';;'.str_replace('.00000','.00 руб.',$res->total_summ);
//подсчитываем сумму общего заказа $query =htmlspecialchars("update #__k2store_orders set is_editing='1',orderpayment_amount ='".$res->total_summ."',order_total ='".$res->total_summ."',order_subtotal ='".$res->total_summ."' where id ='".$order."'"); $db->setQuery($query); if(!$db->query()) { header('HTTP/1.1 500 '.JText::_("Ошибка ID = '".$idToUpd."' '".$db->stderr())); exit(); } exit(); }
После выполнения запроса на форме обновиться сумму единицы и общая сумма заказа.
Также запрос оставляет пометку о том. что было ручное редактирование, для этого необходимо добавить поле в таблицу
ALTERTABLE #__k2store_orders ADDCOLUMN is_editing int(1) AFTER #__k2store_orders;
Обработку этого значения разместим в файле с общим списком заказов, редактируем файл:
Таким же образом можно редактировать стоимость позиции и стоимость опций, добавить скидку(изменение стоимости позиции и опции на определенный процент).
Столкнулся с проблемой, когда для выполнения Ajax запроса необходимо открывать php страницу, но если страница не прописана в MVC модели компонента Joomla, то ее вызов блокируется безопасностью.
Выход из ситуации - записать обработку POST и GET запросов на странице заголовков view.html.php (/administrator-site/view/<Наименование>/)
На примере задачи : На форме расположен input, необходимо разместить кнопку, которая обновит запись в БД, по результату спрятать элементы .
Реализация Script на основной странице:
<script> jQuery("body").on("click", ".btn_ex_save", function(e) { e.preventDefault(); //ищем ID в БД var clickedID = this.id.split("-"); var DbNumberID = clickedID[1]; //данные для отправки POST запросом var myData = 'recordToEx='+DbNumberID+'&recordSTR='+document.getElementById('quant-'+DbNumberID).value; jQuery.ajax({ type: "POST", url: "index.php?option=op1&view=v1",//ссылка на текущую страницу dataType:"text", data:myData, success:function(response){ document.getElementById('div-'+DbNumberID).style.display= "none";}, error:function (xhr, ajaxOptions, thrownError){alert(thrownError);} }); }); }); </script>
K2 store Дорабатываем отправку писем покупателю - письмо о изменении статуса заказа
Компонент k2_Store в стандартной комплектации, при изменении статуса заказа, отправляет один и тот же шаблон покупателю(полный текст заказа- товар, оплата, контакты и тд.)
Появилась необходимость отправлять покупателю письмо с информацией о смене статуса заказа, без подробного отчета о покупке.
Для корректировки этого процесса необходимо внести изменения в файл
/components/com_k2store/helpers/orders.php
Необходимо продублировать функцию "public static function sendUserEmail", но с новыми параметрами, назовем ее "sendUserEmailNotyfy"
public static function sendUserEmailNotyfy($user_id, $order_id, $payment_status, $order_status, $order_state_id) { $mainframe =JFactory::getApplication(); jimport('joomla.filesystem.file'); // grab config settings for sender name and email $config = JFactory::getConfig(); $k2store_params = JComponentHelper::getParams('com_k2store'); $k2params = JComponentHelper::getParams('com_k2'); if(version_compare(JVERSION, '3.0', 'ge')) { $mailfrom = $k2store_params->get('emails_defaultemail', $config->get('mailfrom')); $fromname = $k2store_params->get('emails_defaultname', $config->get('fromname')); } else { $mailfrom = $k2store_params->get('emails_defaultname', $config->getValue('config.mailfrom')); $fromname = $k2store_params->get('emails_defaultname', $config->getValue('config.fromname')); } $sitename = $k2store_params->get( 'sitename', $mainframe->getCfg('sitename') ); $siteurl = $k2store_params->get( 'siteurl', JURI::root() ); //now get the order table's id based on order id $id = self::_getOrderKey($order_id); //inventory //TODO::move this function to the plugin. require_once (JPATH_ADMINISTRATOR.'/components/com_k2store/library/inventory.php'); K2StoreInventory::setInventory($id, $order_state_id); //now get the receipient $recipient = self::_getRecipient($order_id); if($user_id && empty($recipient->billing_first_name)) { $recipient->name = JFactory::getUser($user_id)->name; } else { $recipient->name = $recipient->billing_first_name.' '.$recipient->billing_last_name; } $mailer =JFactory::getMailer(); $mode = 1; $subject = 'Статус вашего заказа был изменен на : '.JText::_($order_status); $tags = array( '[ORDER_ID]' => $id ); foreach ($tags as $key => $value) { $subject = str_replace($key, $id, $subject); } $msg = ''; $msg .= 'Тело письма в формате HTML, формат можно взять из файла components/com_k2store_view/order/orderemail.php'; $admin_emails = trim($k2store_params->get('admin_email')) ; $admin_emails = explode(',',$admin_emails ) ; //send email if ($recipient) { $mailer->addRecipient($recipient->user_email); // $mailer->addCC( $config->get('admin_email')); //$mailer->addCC( $admin_emails ); $mailer->setSubject( $subject ); $mailer->setBody($msg); $mailer->IsHTML($mode); $mailer->setSender(array( $mailfrom, $fromname )); $mailer->send(); } //Если не нужно отправлять дубликат администраторам, то удаляем этот пункт if($admin_emails) { $mailer =JFactory::getMailer(); $mailer->addRecipient($admin_emails); $mailer->setSubject( $subject ); $mailer->setBody($msg); $mailer->IsHTML($mode); $mailer->setSender(array( $mailfrom, $fromname )); $mailer->send(); } return true; }
Следующий шаг - меняем вызов шаблона при смене статуса, редактируем файл
В данном файле находится шаблон письма, предлагаю такой вариант - дополнительно указаны: лого, телефон, ссылки на страницы, изменена подпись, более читаема таблица, контактные данные разбиты по типу.
В шапке документа добавляем короткое меню, лого и телефон:
?> <div style="border-top: 1px dotted black;display: inline-block;line-height: 35px;"> <div style="background-color: #FFCE6E;color: #C0ECFF;"> <span style="margin-left: 30px;"><a style="text-decoration: none;" href="/url">Наш каталог</a></span> <span style="margin-left: 30px;"><a style="text-decoration: none;" href="/url">Контакты</a></span> <span style="margin-left: 30px;"><a style="text-decoration: none;" href="/url">Оплата и доставка</a></span> <span style="margin-left: 30px;"><a style="text-decoration: none;" href="/url">Вопрос-ответ</a></span> </div> <div><a href="/url"><img src="http://site/images/logos.png" style="margin-right: 200px;"></a><div style="float:right;color:#FF8811;margin-top: 18px;margin-right: 27px;">Тел:+</div> <div class="k2store_ordermail_header" style="border-top: 1px dotted black;"> <?php echo 'Здравствуйте! '.$recipient_name.'<br> Мы благодарим вас за размещение заказа на сайте '.$this->sitename.'</span>'; echo '<br>Ваш заказ принят в обработку. В ближайшее время с Вами свяжется наш менеджер для подтверждения заказа.'; ?> </div> <div id="k2store_order_info">
Далее немного доработаем вывод информации -адрес, телефон, почта и тд, в стандартном шаблоне все выводится в одну строку, мы же разабъем на типы
<?php if ($row->orderpayment_type == 'payment_offline') { ?> <strong>Оплата наличными курьеру/ Доставка по г. Новосибирску</strong> <?php echo JText::_($row->transaction_details); ?><br> <?php } ?>
<?php if ($row->orderpayment_type == 'payment_cash') { ?> <strong>Оплата наличными курьеру/Доставка в отдаленные районы г. Новосибирска - 200 р.</strong> <?php echo JText::_($row->transaction_details); ?><br> <?php } ?> <?php if ($row->orderpayment_type == 'payment_banktransfer') { ?> <strong>100 % оплата / Доставка в другой город</strong> <?php echo JText::_($row->transaction_details); ?><br> <?php } ?> <?php if ($row->orderpayment_type == 'Офлайн платёж') { ?> <strong>Оплата наличными курьеру/ Доставка по г. Новосибирску</strong><?php } ?>
В подвале вставим информацию, что не нужно отвечать на это письмо и выделим заливкой:
</div> <br> <div style="background-color: #DEDEDE;">Данное сообщение отправлено автоматически, пожалуйста, не отвечайте на него.</div> <?php if(!$this->isGuest): //show only if the buyer is not a guest. Because a guest cannot access the stored order information ?> <div class="k2store_ordermail_footer" style="background-color: #C8E5FF;border-top: 1px dotted black;"> <?php echo JText::sprintf('K2STORE_ORDER_PLACED_FOOTER', '<br>'.$this->siteurl.'index.php?option=com_k2store&view=orders&task=view&id='.$row->id); ?> </div> <?php else:?> <div class="k2store_ordermail_footer" style="background-color: #C8E5FF;border-top: 1px dotted black;"> <?php echo JText::sprintf('K2STORE_ORDER_GUEST_TOKEN', '<br>'.$this->siteurl.'index.php?option=com_k2store&view=orders&task=view', $order->token); ?> </div> </div>
Редактируем корзину K2_Store - добавляем номер заказа на страницу оформления товара
На странице оформления товара, после размещения товара хочется вывести дополнительную информацию.
Компонент формирует ссылку и отправляет письмо, но покупатель хочет получить все и сразу.
Для редактирования этой страницы откройте файл:
com_k2store/checkout/postpayment.php
Далее добавляем необходимую информацию, например номер заказа и текст о магазине в блоке(Номер заказа будет выводиться, только для зарегистрированного пользователя) <div class="note">:
<div class="note"> <p>Номер Вашего заказа - <?php echo substr($order_link,strpos($order_link,'view/')+5);?></p> <br> <p>Спасибо за покупку в интернет-магазине «Pooof.ru».</p> <br> <p>Менеджер свяжется с вами в ближайшее время.</p> <br> <a href="/<?php echo JRoute::_($order_link); ?>"> <?php echo JText::_( "K2STORE_VIEW_PRINT_INVOICE" ); ?> </a> </div>
Покупка в 1 клик и автосумма выбранной опции в K2_Store
Иногда базового функционала не достаточно, и для улучшения продаж на сайте добавляют "Покупку за 1 клик" - это скрипт формы обратной связи, у покупателя просят ввести свои данные(почта, телефон) и скрипт отправляет администратору магазина информацию о желании клиента купить товар, далее менеджеры связываются и обсуждают варианты продажи и доставки.
Проблема в Joomla в том, что многие модули используют разные версии jquery и совместить новый функционал иногда не получается.
Для внедрения "покупки за 1 клик" можно использовать скрипт jbOneClick
Подключение скрипта:
1.Необходимо в <HEAD> прописать скрипт и CSS файл:
2.На каждой странице(на ваше усмотрение) необходимо выводить функцию обработки нажатия на кнопку,я добавил в самый конец страницы, перед закрывающим тегов </BODY>:
5.В k2_store нет автосуммы - после выбора платной опции на товаре не обновляется цена. Этот пункт и вывод выбранной опции можно исправить используя эту функцию:
<script> function set_to_click(id,elem,elem_id,sel) { var btns = document.getElementById('callme_order_btn_'+id); //Отправляем выбранные значения var bo = document.getElementById('data_product_'+id); if (bo.innerHTML == '') {bo.innerHTML = btns.getAttribute("data-product")} var bc = document.getElementById('data_product_price_'+id); if (bc.innerHTML == '') {bc.innerHTML = document.getElementById('product_price_'+id).innerHTML} //читаем стоимость опции var op = document.getElementById('product_option['+elem_id+']').options[sel].text; if (op.indexOf('(')<=1) {var op_cash = '0';} else { var op_cash = op.substring(op.indexOf('(')+2, op.indexOf('.')).replace(',', '');} //читаем стоимость товара var tov = document.getElementById('data_product_price_'+id).innerHTML; tov_cash=tov.replace(/\s{2,}/g, ' '); tov_cash=tov_cash.substring(1, tov_cash.indexOf('.')).replace(',', ''); //суммируем и форматируем new_tov=Number(op_cash)+Number(tov_cash); new_tov=new_tov+'.00 руб.'; new_tov=new_tov.replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1,'); //вывод document.getElementById('product_price_'+id).innerHTML = new_tov; btns.setAttribute("data-product",bo.innerHTML+' '+elem+' "'+op); } </script>
Для ее реализации необходимо скорректировать файл:
com_k2store/mycart/addtocart_options.php
Перед циклом опроса опций, необходимо добавить блоки, для запоминания базовой цены и значения атрибуту кнопки:
// no direct access defined( '_JEXEC' ) or die( 'Restricted access' ); $options = $this->attributes; $db = JFactory::getDbo(); ?> <?php if ($options) { ?> <div class="options" style="margin-bottom: 15px;"> <div id="data_product_<?php echo $this->item->id;?>" style="display:none"></div> <div id="data_product_price_<?php echo $this->item->id;?>" style="display:none"></div> <?php foreach ($options as $option) { ?>
Далее всем необходимым элементам добавить вызов функции, мне понадобился только <select>:
Вы можете самостоятельно разместить QR код в любом месте, для этого можно воспользоваться сервисом http://www.bosqweb.net, в текст достаточно вставить этот тег:
Цель данной модификации - сделать точный рейтинг материалов, по месяцам,датам и даже времени.
Стандартная функция подсчета кликов ведет только кол-во кликов за все время, но в одном из проектов нам понадобилась статистика просмотров в разрезе месяца.
Что нам понадобится:
1.Создаем таблицу #__k2_hits:
CREATE TABLE `#__k2_hits` ( `id` int(11) NOT NULL AUTO_INCREMENT, `k2_id` varchar(100) COLLATE utf8_unicode_ci NOT NULL, `insert_date` datetime COLLATE utf8_unicode_ci NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
2.Добавляем функцию, которая сохранит данные просмотра. Редактируем файл:
/public_html/components/com_k2/models/item.php
Дорабатываем функцию hit:
function hit($id) {$row = JTable::getInstance('K2Item', 'Table'); $row->hit($id); $db = JFactory::getDBO(); $query = "insert into #__k2_hits(k2_id,insert_date,type) values(".$id.",'".date("Y-m-d H:i:s")."','items');"; $db->setQuery($query); $db->query(); }
Дорабатываем K2 (2.6.9) и K2_store - выгрузка на яндекс маркет, формат YML
Для автоматизации выгрузки можно использовать PHP скрипт.
Нам необходимо подготовить таблицу - добавить 3 поля (yan_model,yan_vendor,yan_typePrefix) в таблицу #_k2_items, кроме того необходимо настроить редактирование из административной части k2, как это сделать написано в статье (на примере поля "relateditems"): Дорабатываем K2 (2.6.9) - управляемые рекомендации Related Items
От себя:
1.Скрипт сделан на скорую руку, не претендует на окончательное решение, возможно будет выпущен плагин для joomla 3x
2.Значение производителя, префикса и модели сделано через отдельную колонку, т.к. колонка с названием товара не подходит, реализация через extrafields слишком сложна(будет реализовано в плагине для joomla) для внешнего скрипта
3.Категории магазина не совпадают с яндексом, также в магазине не храниться информация о производителе, поэтому эти данные вынесены в отдельные колонки - это позволяет более гибко работать с названием товара
4.Скрипт опробован на действующем магазине, экспорт в яндекс маркет происходит без ошибок
5.Реализована проверка на экспорт - если не заполнена одна из колонок (yan_model,yan_vendor,yan_typePrefix), товар не попадет в файл YML и не будет выгружен на маркет
6.Описание товара для маркета берется из поля "fulltext" таблицы #_k2_items, можно отключить переменной $show_desc
7.Скрипт представлен не полностью, только демонстрационная часть
Скрипт:
<?php /*Вывод ошибок - блок нужен для отладки*/ //ini_set('error_reporting', E_ALL); //ini_set('display_errors', 1); //ini_set('display_startup_errors', 1);
//ссылка на файл конфигурации include_once ("configuration.php"); $datas = new JConfig; $hostname = $datas->host; $username = $datas->user; $password = $datas->password; $dbName = $datas->db; $mysite = $datas->sitename; // Ваш сайт $filename = 'yandex.xml'; // размещение xml файла $db_pref ='Jos_'; //префикс таблиц $mag_name ='Название магазина'; //Название магазина $comp_name ='Название фирмы'; //Название компании $show_desc = 1;// [0-нет 1-да] выводить описание товаров $loc_del = '150'; //стоимость доставки $menu_url = 1;//[0-формат index.php?option=com_k2&view=item&layout=item&id= 1-alias из таблицы #_menu]способ формирование url
$category = $db_pref."k2_categories";//таблица категорий $itemtable = $db_pref."k2_items"; //таблица товаров $pricetable = $db_pref."k2store_products";//таблица с ценами $product_menu_xref = $db_pref."menu";//ссылка на меню, используется для извлечения alias
mysql_connect($hostname,$username,$password) OR DIE("Не могу соединиться базой данных Mysql"); mysql_select_db($dbName) or die(mysql_error()); $xmlfile = fopen($filename,'w+');
$xmltext = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; $xmltext .= "<!DOCTYPE yml_catalog SYSTEM \"shops.dtd\">\n"; $xmltext .= "<yml_catalog date=\""; $xmltext .= date('Y-m-d H:i'); $xmltext .= "\">\n"; $xmltext .= "<shop>\n"; $xmltext .= "<name>$mag_name</name>\n"; $xmltext .= "<company>$comp_name</company>\n"; $xmltext .= "<url>http://$mysite</url>\n"; $xmltext .= "<currencies>\n"; $xmltext .= "<currency id=\"RUR\" rate=\"1\"/>\n"; $xmltext .= "</currencies>\n";
$xmltext .= "<categories>\n"; try{
mysql_query("SET CHARACTER SET 'cp_1251_general_ci'"); $query_cat = "SELECT * FROM $category where published = '1' "; $res_cat = mysql_query($query_cat) or die(mysql_error()); $rw=1;
while ($row_cat=mysql_fetch_array($res_cat)) { $cat_parent_id=$row_cat['parent']; $cat_child_id=$row_cat['id']; //Строим дочернюю ветку $query_cat_sub = "SELECT name FROM $category WHERE published = '1' and id=".$row_cat['id']; $res_cat1 = mysql_query($query_cat_sub) or die(mysql_error()); $name_cat=mysql_fetch_array($res_cat1); $cat_name=$name_cat['name']; $cat_name= htmlspecialchars($cat_name, ENT_QUOTES);
if ($cat_parent_id==0) { $xmltext .= "<category id=\"".$cat_child_id."\">".$cat_name."</category>\n"; } else { $xmltext .= "<category id=\"".$cat_child_id."\" parentId=\"".$cat_parent_id."\">".$cat_name."</category>\n"; } $rw++;
Дорабатываем компонент записи на прием Appointment Book Manager 1.4.1 (jxtcappbook) - добавляем места
В данной статье расскажу, как реализовали запись в класс, через компонент Appointment Book Manager.
Стандартная реализация позволяет зарегистрировать 1 человека в один отведенный час, после чего выводилась отметка, что данный час занят. Нам требовалось плавающие значение от 3 до 23 человек на один час.
// вычисляем кол-во занятых мест $query = 'SELECT *,dayofmonth(date) as day FROM #__jxtc_appbook_appointments WHERE published=1 AND parent_id=' . $this->calendar_id . ' AND year(date) = ' . $this->y . ' AND month(date) = ' . $this->m . ' and start="'.$startKey.'" ORDER BY date, start'; $db->setQuery($query); $appointments = $db->loadObjectList(); $app_count = $db->getAffectedRows ();
Если вы правильно все сделали, то в административной части, при редактировании календаря, можно указать кол-во свободных мест. В лицевой части появится "Места". как показано на изображении.
Дорабатываем K2 (2.6.9) - управляемые рекомендации Related Items
В одном из проектов потребовалось управлять рекомендациями, которые отображаются на странице товара. Стандартный механизм K2 - это вывод материал по похожим тегам - это очень не удобно.
Выход прост - привязать иденты материалов для вывода рекомендаций.
Пролистав возможные решения (плагины, компоненты) для K2, стало понятно что нужно менять родной механизм, что мы делаем:
Дорабатываем таблицу и запрос выбора тегов
1.Добавляем поле "relateditems" в таблицу #__k2_items . Обязательно указать значение по умолчанию "0" ! Регистр букв важен, пишите все в нижнем, иначе компонент не сможет сопоставить поле.
2.Необходимо изменить файл с функцией выбора тегов "function getRelatedItems($itemID, $tags, $params)":
/components/com_k2/models/itemlist.php
В функции заменить:
$query = "SELECT DISTINCT itemID FROM #__k2_tags_xref WHERE tagID IN ({$sql}) AND itemID!={$itemID}";
На:
$query = "SELECT DISTINCT relateditemsFROM #__k2_items WHERE ID ={$itemID}";
Первый этап готов, достаточно в таблице #__k2_items в поле relatedItems перечислить иденты товаров и они появятся в списке рекомендаций.
В административной части реализуем механизм редактирования колонки relateditems
Редактируем список полей элемента в административной части, добавляем поле для ввода:
var $created_by_alias = null; var $relateditems = null;
Иденты нужно будет вводить как в SQL запросе, через запятую. Следите за правильностью ввода данных, поле не должно быть пустым и содержать некорректные данные(например лишняя запятая), иначе на странице будет ошибка.
Список рекомендаций не появиться, если у товара нет тега. Достаточно добавить 1 тег. Если вы подробно ведете номенклатуру, этот момент вас не смутит, также можно самостоятельно исправить выборку, я не стал трогать этот момент.
1.Меняем фон всплывающего окна, я сделал серый градиент, прозрачное окно и черный текст.Также в этом правиле выставляется на сколько окно "вынернет" при формировании списка top:70%; :