Задача и описание ситуации:
При возделывании магазина на Джумле 1.0.12 + Virtuemart RE 1.0.12 досталась база товаров цена которых в базе была в долларах. Так как Виртумарт одновалютный и не позволяет конвертировать валюту при выводе товаров на сайте в рублях, то пришлось залезть в /administrator/components/com_virtuemart/classes/ps_product.php и в function show_price изменить строку
$base_price = $base_price_info["product_price"];
на
// Расчёт базовой цены по курсу 25руб за 1$
// $base_price = ($base_price_info["product_price"])*25;
Но это было тупое умножение цены товара на 25 и не позволяла клиенту менять курс по своему умотрению без моей помощи. Так что нужно было сделать чё нить другое, более полезное и удобное. Не вздумайте вставлять вышеописанный код, дочитайте до конца…))
Нужно было найти хак или модуль по конвертации с возможностью изменения курса на каждую валюту отдельно. Чего я так и не нашёл ни на одном из ворумов.
Итак, как я уже сказал искал 2 дня этот хак на форуме
http://forum.virtuemart.ru, а так же на этом форуме. Но ничего не нашёл ни по поиску ни по другим параметрам. Набрёл вот на эту тему с хорошей ссылкой на
http://ru-mambo.ru/smf/index.php/topic,11897.0.html.
Возникла идея доделать и немного отредактировать то что нужно многим из нас. Далее пошагово:
1) Заходим в БД магазина и в таблице jos_vm_currency создаём дополнительное поле currency_curs (я назвал его currency_curs, SB назвал свой «currency_rate», то так как я русский человек то слово «курс(curs)» мне болиже чем «рэйт(rate)»), с типом данных «decimal(11,2), значение по умолчанию 1 ибо если будет 0, то цена превратиться в 0, если неправильно будет выбрана валюта отображения товара на сайте.
2) Далее нам нужно поле формы в админке для редактирования стоимости каждой из валют.
Заходим в админке: в компонент магазина -> Настройки -> Валюта –> Список валют. Выбираем валюту нажатием на её ссылку. Видим 2 поля формы: Название и код валюты, которые беруться из вышеописанной базы. Нам нужно добавить 3-е поле ввода для редактирования курса этой валюты.
/administrator/components/com_virtuemart/html/admin.curr_form.php – ищем HTML+PHP код :
<tr>
<td width="24%" align="right"><?php echo $VM_LANG->_PHPSHOP_CURRENCY_LIST_CODE ?>:</td>
<td width="76%">
<input type="text" class="inputbox" name="currency_code" value="<?php $db->sp("currency_code") ?>" />
</td>
</tr>
Добавляем под ним новую строку таблицы:
<tr>
<td width="24%" align="right">Курс в рублях:</td>
<td width="76%">
<input type="text" class="inputbox" name="currency_curs" value="<?php $db->sp("currency_curs") ?>" />
</td>
</tr>
Лично мне было влом в лэнгвиче добавлять новую переменную, и тупо написал «Курс в рублях:». Кому надо можете поставить свой текст по личному желанию.
3) Теперь нужно сделать так чтоб новая строка формы «Курс в рублях» брала значения из БД и если надо то редактировала, при апдэйте или создании новой валюты. Короче делаем её функциональной:
/administrator/components/com_virtuemart/classes/ps_currency.php – ищем заветный код со словами Инсерт и Апдэйт.))
function add – в этой функции добавляем обработчик нового поля в таблице «Куренси» нашей БД. Заменяем похожее на это:
$q = "INSERT INTO #__{vm}_currency (currency_name, currency_curs, currency_code)";
$q .= " VALUES ('";
$q .= $d["currency_name"] . "','";
$q .= $d["currency_curs"] . "','";
$q .= $d["currency_code"] . "')";
В функции function update делаем тоже самое:
$q = "UPDATE #__{vm}_currency set ";
$q .= "currency_name='" . $d["currency_name"];
$q .= "',currency_curs='" . $d["currency_curs"]."' ";
$q .= ",currency_code='" . $d["currency_code"]."' ";
$q .= "WHERE currency_id='".$d["currency_id"]."'";
Заливаем файлы на сервер и обновляем станицу в админке. Вау! Круто! Теперь у нас на каждую валюту свой рублёвый множитель.
4) Теперь нужно заставить этот множитель работать. Исходник кода я взял у SB «3. В классе ps_product добавляется расчет курса в соответствии с валютой товара и магазина. (функции get_retail_price и get_price).» на форуме мамбы, и внёс некоторые корректировки по перемене имён переменных на свои.
/administrator/components/com_virtuemart/classes/ps_product.php – ищем функцию function get_retail_price.
Над функцией по аналогии с предложенным SB вставляем новую функцию:
/**************************************************************************
** name: get_cur_rate($price_info, $vendor_id)
** created by: sb
** modify by: XDX
** description: get currency curs!!!
** parameters:
** returns:
***************************************************************************/
function get_curs_rate($price_info, $vendor_id) {
$db = new ps_DB;
// Get the vendor id for this product.
$q = "SELECT vendor_currency FROM #__{vm}_vendor WHERE vendor_id='$vendor_id'";
$db->setQuery($q); $db->query();
$db->next_record();
$vendor_currency = $db->f("vendor_currency");
if ($price_info["product_currency"] !== $vendor_currency)
{
$price_info_product_currency = $price_info["product_currency"];
$q = "SELECT currency_curs FROM #__{vm}_currency WHERE currency_code = '$price_info_product_currency' ";
$db->setQuery($q); $db->query();
$db->next_record();
$currency_curs = $db->f("currency_curs");
//error_log ($currency_curs, 3, "my-errors.log");
if($currency_curs)
{
return $currency_curs;
}
}
return 1;
}
Далее в функциях get_retail_price и get_price вставляем нужные части кода предложенного SB. Я не буду подробно описывать, что и после какой строки вставлять, просто скопирую сюда сразу код этих функций благо они идут одна за другой:
/**
* Function to get the "pure" undiscounted and untaxed price
* of product $product_id. Used by the administration section.
*
* @param int $product_id
* @return array The product price information
*/
function get_retail_price($product_id) {
$db = new ps_DB;
$curs = 0;
// Get the vendor id for this product.
$q = "SELECT vendor_id FROM #__{vm}_product WHERE product_id='$product_id'";
$db->setQuery($q); $db->query();
$db->next_record();
$vendor_id = $db->f("vendor_id");
// Get the default shopper group id for this product and user
$q = "SELECT shopper_group_id FROM #__{vm}_shopper_group WHERE `vendor_id`='$vendor_id' AND `default`='1'";
$db->setQuery($q); $db->query();
$db->next_record();
$default_shopper_group_id = $db->f("shopper_group_id");
$q = "SELECT product_price,product_currency FROM #__{vm}_product_price WHERE product_id='$product_id' AND ";
$q .= "shopper_group_id='$default_shopper_group_id'";
$db->setQuery($q); $db->query();
if ($db->next_record()) {
$price_info["product_price"]= $db->f("product_price");
$price_info["product_currency"]=$db->f("product_currency");
}
else {
$price_info["product_price"]= "";
$price_info["product_currency"] = $_SESSION['vendor_currency'];
}
$curs = $this->get_curs_rate($price_info, $vendor_id);
if (($cur)&&(!$original_price))
$price_info["product_price"]=$price_info["product_price"] * $curs;
return $price_info;
}
/**
* Get the price of product $product_id for the shopper group associated
* with $auth['user_id'] - including shopper group discounts
*
* @param int $product_id
* @param boolean $check_multiple_prices Check if the product has more than one price for that shopper group?
* @return array The product price information
*/
function get_price($product_id, $check_multiple_prices=false) {
$auth = $_SESSION['auth'];
$cart = $_SESSION['cart'];
if( empty( $GLOBALS['product_info'][$product_id]['price'] )
|| !empty($GLOBALS['product_info'][$product_id]['price']["product_has_multiple_prices"])
|| $check_multiple_prices) {
$db = new ps_DB;
if( empty( $_SESSION['product_sess'][$product_id]['vendor_id'] )) {
// Get the vendor id for this product.
$q = "SELECT vendor_id FROM #__{vm}_product WHERE product_id='$product_id'";
$db->setQuery($q); $db->query();
$db->next_record();
$_SESSION['product_sess'][$product_id]['vendor_id'] = $vendor_id = $db->f("vendor_id");
}
else {
$vendor_id = $_SESSION['product_sess'][$product_id]['vendor_id'];
}
$shopper_group_id = $auth["shopper_group_id"];
$shopper_group_discount = $auth["shopper_group_discount"];
if( empty($GLOBALS['vendor_info'][$vendor_id]['default_shopper_group_id']) ) {
// Get the default shopper group id for this vendor
$q = "SELECT shopper_group_id,shopper_group_discount FROM #__{vm}_shopper_group WHERE ";
$q .= "vendor_id='$vendor_id' AND `default`='1'";
$db->setQuery($q); $db->query();
$db->next_record();
$GLOBALS['vendor_info'][$vendor_id]['default_shopper_group_id'] = $default_shopper_group_id = $db->f("shopper_group_id");
$GLOBALS['vendor_info'][$vendor_id]['default_shopper_group_discount']= $default_shopper_group_discount = $db->f("shopper_group_discount");
}
else {
$default_shopper_group_id = $GLOBALS['vendor_info'][$vendor_id]['default_shopper_group_id'];
$default_shopper_group_discount = $GLOBALS['vendor_info'][$vendor_id]['default_shopper_group_discount'];
}
// Get the product_parent_id for this product/item
$product_parent_id = $this->get_field($product_id, "product_parent_id");
$price_info = Array();
if( !$check_multiple_prices ) {
/* Added for Volume based prices */
// This is an important decision: we add up all product quantities with the same product_id,
// regardless to attributes. This gives "real" volume based discount, because our simple attributes
// depend on one and the same product_id
$quantity = 0;
for ($i=0;$i<$cart["idx"];$i++) {
if ($cart[$i]["product_id"] == $product_id) {
$quantity += $cart[$i]["quantity"];
}
}
$volume_quantity_sql = " AND (('$quantity' >= price_quantity_start AND '$quantity' <= price_quantity_end)
OR (price_quantity_end='0') OR ('$quantity' > price_quantity_end)) ORDER BY price_quantity_end DESC";
/* End Addition */
}
else {
$volume_quantity_sql = " ORDER BY price_quantity_start";
}
// Getting prices
//
// If the shopper group has a price then show it, otherwise
// show the default price.
if( !empty($shopper_group_id) ) {
$q = "SELECT product_price, product_price_id, product_currency FROM #__{vm}_product_price WHERE product_id='$product_id' AND ";
$q .= "shopper_group_id='$shopper_group_id' $volume_quantity_sql";
$db->setQuery($q); $db->query();
if ($db->next_record()) {
$price_info["product_price"]= $db->f("product_price");
if( $check_multiple_prices ) {
$price_info["product_base_price"]= $db->f("product_price");
$price_info["product_has_multiple_prices"] = $db->num_rows() > 1;
}
$price_info["product_price_id"]=$db->f("product_price_id");
$price_info["product_currency"]=$db->f("product_currency");
$price_info["item"]=true;
$curs = $this->get_curs_rate($price_info, $vendor_id);
if ($curs)
$price_info["product_price"]=$price_info["product_price"] * $curs;
$GLOBALS['product_info'][$product_id]['price'] = $price_info;
return $GLOBALS['product_info'][$product_id]['price'];
}
}
// Get default price
$q = "SELECT product_price, product_price_id, product_currency FROM #__{vm}_product_price WHERE product_id='$product_id' AND ";
$q .= "shopper_group_id='$default_shopper_group_id' $volume_quantity_sql";
$db->setQuery($q); $db->query();
if ($db->next_record()) {
$price_info["product_price"]=$db->f("product_price") * ((100 - $shopper_group_discount)/100);
if( $check_multiple_prices ) {
$price_info["product_base_price"]= $price_info["product_price"];
$price_info["product_has_multiple_prices"] = $db->num_rows() > 1;
}
$price_info["product_price_id"]=$db->f("product_price_id");
$price_info["product_currency"] = $db->f("product_currency");
$price_info["item"] = true;
$curs = $this->get_curs_rate($price_info, $vendor_id);
if ($curs)
$price_info["product_price"]=$price_info["product_price"] * $curs;
$GLOBALS['product_info'][$product_id]['price'] = $price_info;
return $GLOBALS['product_info'][$product_id]['price'];
}
// Maybe its an item with no price, check again with product_parent_id
if( !empty($shopper_group_id) ) {
$q = "SELECT product_price, product_price_id, product_currency FROM #__{vm}_product_price WHERE product_id='$product_parent_id' AND ";
$q .= "shopper_group_id='$shopper_group_id' $volume_quantity_sql";
$db->setQuery($q); $db->query();
if ($db->next_record()) {
$price_info["product_price"]=$db->f("product_price");
if( $check_multiple_prices ) {
$price_info["product_base_price"]= $db->f("product_price");
$price_info["product_has_multiple_prices"] = $db->num_rows() > 1;
}
$price_info["product_price_id"]=$db->f("product_price_id");
$price_info["product_currency"] = $db->f("product_currency");
$curs = $this->get_curs_rate($price_info, $vendor_id);
if ($curs)
$price_info["product_price"]=$price_info["product_price"] * $curs;
$GLOBALS['product_info'][$product_id]['price'] = $price_info;
return $GLOBALS['product_info'][$product_id]['price'];
}
}
$q = "SELECT product_price, product_price_id, product_currency FROM #__{vm}_product_price WHERE product_id='$product_parent_id' AND ";
$q .= "shopper_group_id='$default_shopper_group_id' $volume_quantity_sql";
$db->setQuery($q); $db->query();
if ($db->next_record()) {
$price_info["product_price"]=$db->f("product_price") * ((100 - $shopper_group_discount)/100);
if( $check_multiple_prices ) {
$price_info["product_base_price"]= $price_info["product_price"];
$price_info["product_has_multiple_prices"] = $db->num_rows() > 1;
}
$price_info["product_price_id"]=$db->f("product_price_id");
$price_info["product_currency"] = $db->f("product_currency");
$curs = $this->get_curs_rate($price_info, $vendor_id);
if ($curs)
$price_info["product_price"]=$price_info["product_price"] * $curs;
$GLOBALS['product_info'][$product_id]['price'] = $price_info;
return $GLOBALS['product_info'][$product_id]['price'];
}
// No price found
$GLOBALS['product_info'][$product_id]['price'] = false;
return $GLOBALS['product_info'][$product_id]['price'];
}
else {
return $GLOBALS['product_info'][$product_id]['price'];
}
}
Честно говоря не проверял получившиеся функции на чистоту и всевозможные багги, просто переименовал переменные на свои. Если кто найдёт ошибки тот молодец, я ему буду очень благодарен.
Теперь мы имеем достойный калькулятор валют в нашем магазине. И клиент не будет парить вам мозг по изменению курса валюты.
Спасибо за внимание. Доработка приветствуется!)))