Jump to content

Сделаем мультивалюту вместе? (PS 1.5)


Recommended Posts

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

 

Вкратце, что мне (и думаю другим тоже) нужно:

- Prestashop 1.5.6.2;

- основная валюта в БД имеет номер 1;

- есть поставщики, с которыми я расплачиваюсь в любой валюте (это не суть важно);

- цены в моем магазине должны равняться розничной цене поставщика (в его валюте) * курс моей валюты по отношению к их валюте; ГОТОВО!

- при изменении курса валюты в магазине нужно автоматом пересчитать цены товаров с этой же валютой (ручками пересчитывать и перебивать по 100-200 товаров при изменении курса уже надоело).

 

ВНИМАНИЕ! Всё, что будет дальше, я делал под свои конкретные требования, условия и настройки магазина. Я не могу гарантировать работоспособность всего этого в вашем магазине с вашими настройками и пр.

Из того, что я уже проделал:

1. В таблицу %_DB_PREFIX_%product добавил два поля: base_price типа decimal(20,6) и base_currency типа tinyint(1).

2. Создал файл /override/classes/Product.php:

<?php 
Class Product extends ProductCore
{
  public $base_price = 0;

  public $base_currency = 1;
 
    public function __construct($id_product = null, $full = false, $id_lang = null, $id_shop = null, Context $context = null)
    {
        self::$definition['fields']['base_price'] = array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice');
        self::$definition['fields']['base_currency'] = array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt');
        parent::__construct($id_product, $full, $id_lang, $id_shop, $context);
    }   
}
?> 
3. Создал файл /override/controllers/admin/templates/products/prices.tpl, в котором в нужном мне месте добавил кусок кода:

	<tr>
		<td class="col-left">
			<label>{l s='Base price:'}</label>
		</td>
		<td style="padding-bottom:5px;">
		
			<input size="11" maxlength="14" name="base_price" id="base_price" type="text" value="{$product->base_price|string_format:'%.2f'}" onkeyup="this.value = this.value.replace(/,/g, '.'); $('#base_currency').change();" />
			<select name="base_currency" id="base_currency">
			{foreach from=$currencies item=c}
				<option value="{$c.id_currency}"{if ($c.id_currency == $product->base_currency)} selected="selected"{/if} rate="{$c.conversion_rate}">{$c.name}</option>
			{/foreach}
			</select>

			<p class="preference_description">{l s='Manufacturer\'s recommended price'}</p>
		</td>
	</tr>
3а. В то же файле /override/controllers/admin/templates/products/prices.tpl в самом начале есть блок javascript, туда добавил перед закрывающим тегом:

$("#base_currency").change(function () {
    $('#priceTE').val(ps_round($('#base_price').val() / $("#base_currency option:selected").attr('rate'), 2));
  })
4. Создал файл /override/controllers/admin/AdminProductsController.php, в котором поменял только одну строчку ($currencies = Currency::getCurrencies() ;):

<?php
class AdminProductsController extends AdminProductsControllerCore
{

	public function initFormPrices($obj)
	{
		$data = $this->createTemplate($this->tpl_form);
		$product = $obj;
		if ($obj->id)
		{
			$shops = Shop::getShops();
			$countries = Country::getCountries($this->context->language->id);
			$groups = Group::getGroups($this->context->language->id);
//			$currencies = Currency::getCurrencies();
			$currencies = Currency::getCurrencies(false,false);
			$attributes = $obj->getAttributesGroups((int)$this->context->language->id);
			$combinations = array();
			foreach ($attributes as $attribute)
			{
				$combinations[$attribute['id_product_attribute']]['id_product_attribute'] = $attribute['id_product_attribute'];
				if (!isset($combinations[$attribute['id_product_attribute']]['attributes']))
					$combinations[$attribute['id_product_attribute']]['attributes'] = '';
				$combinations[$attribute['id_product_attribute']]['attributes'] .= $attribute['attribute_name'].' - ';

				$combinations[$attribute['id_product_attribute']]['price'] = Tools::displayPrice(
					Tools::convertPrice(
						Product::getPriceStatic((int)$obj->id, false, $attribute['id_product_attribute']),
						$this->context->currency
					), $this->context->currency
				);
			}
			foreach ($combinations as &$combination)
				$combination['attributes'] = rtrim($combination['attributes'], ' - ');
			$data->assign('specificPriceModificationForm', $this->_displaySpecificPriceModificationForm(
				$this->context->currency, $shops, $currencies, $countries, $groups)
			);

			$data->assign('ecotax_tax_excl', $obj->ecotax);
			$this->_applyTaxToEcotax($obj);

			$data->assign(array(
				'shops' => $shops,
				'admin_one_shop' => count($this->context->employee->getAssociatedShops()) == 1,
				'currencies' => $currencies,
				'countries' => $countries,
				'groups' => $groups,
				'combinations' => $combinations,
				'multi_shop' => Shop::isFeatureActive(),
				'link' => new Link()
			));
		}
		else
		{
			$this->displayWarning($this->l('You must save this product before adding specific pricing'));
			$product->id_tax_rules_group = (int)Product::getIdTaxRulesGroupMostUsed();
			$data->assign('ecotax_tax_excl', 0);
		}

		// prices part
		$data->assign(array(
			'link' => $this->context->link,
			'currency' => $currency = $this->context->currency,
			'tax_rules_groups' => TaxRulesGroup::getTaxRulesGroups(true),
			'taxesRatesByGroup' => TaxRulesGroup::getAssociatedTaxRatesByIdCountry($this->context->country->id),
			'ecotaxTaxRate' => Tax::getProductEcotaxRate(),
			'tax_exclude_taxe_option' => Tax::excludeTaxeOption(),
			'ps_use_ecotax' => Configuration::get('PS_USE_ECOTAX'),
		));

		$product->price = Tools::convertPrice($product->price, $this->context->currency, true, $this->context);
		if ($product->unit_price_ratio != 0)
			$data->assign('unit_price', Tools::ps_round($product->price / $product->unit_price_ratio, 2));
		else
			$data->assign('unit_price', 0);
		$data->assign('ps_tax', Configuration::get('PS_TAX'));

		$data->assign('country_display_tax_label', $this->context->country->display_tax_label);
		$data->assign(array(
			'currency', $this->context->currency,
			'product' => $product,
			'token' => $this->token
		));

		$this->tpl_form_vars['custom_form'] = $data->fetch();
	}

}
?>
10. Конфигурация -> Результат -> Очистить кэш Smarty и кэш Автозагрузки. Edited by m_slon (see edit history)
  • Like 1
Link to comment
Share on other sites

Блин, говорила же мне мама: "Сынок, ходи в универ. Успеешь ещё с друзьями нагуляться..." Теперь вот за 15 лет перерыва программирование (тем более под престу) с трудом, но даётся.

 

Т.е. нужно получить массив через эту команду. Вопрос - в какой из файлов в override это лучше всего вписать?

Уже не актуально, добавил п.4.

 

Далее модифицировал /override/controllers/admin/templates/products/prices.tpl, теперь мой кусок выглядит так:

	<tr>
		<td class="col-left">
			<label>{l s='Base price:'}</label>
		</td>
		<td style="padding-bottom:5px;">
			<input size="11" maxlength="14" name="base_price" id="base_price" type="text" value="{$product->base_price|string_format:'%.2f'}" onchange="this.value = this.value.replace(/,/g, '.');" />
			<select name="base_currency" id="base_currency"">
			{foreach from=$currencies item=c}
				<option value="{$c.id_currency}"{if ($c.id_currency == $product->base_currency)} selected="selected"{/if} onselect="document.getElementById('priceTE').value = document.getElementById('base_price').value * {$c.conversion_rate};">{$c.name}</option>
			{/foreach}
			</select>

			<p class="preference_description">{l s='Manufacturer\'s recommended price'}</p>
		</td>
	</tr>
И генерирует такой код:

<tr>
		<td class="col-left">
			<label>Base price:</label>
		</td>
		<td style="padding-bottom:5px;">
			<input size="11" maxlength="14" name="base_price" id="base_price" type="text" value="10.00" onchange="this.value = this.value.replace(/,/g, '.');">
			<select name="base_currency" id="base_currency">
							<option value="5" selected="selected" onselect="document.getElementById('priceTE').value = document.getElementById('base_price').value * 1.457279;">Czech koruna</option>
							<option value="6" onselect="document.getElementById('priceTE').value = document.getElementById('base_price').value * 0.221318;">Złoty</option>
							<option value="1" onselect="document.getElementById('priceTE').value = document.getElementById('base_price').value * 1.000000;">Гривна</option>
							<option value="3" onselect="document.getElementById('priceTE').value = document.getElementById('base_price').value * 0.068031;">Доллар</option>
							<option value="2" onselect="document.getElementById('priceTE').value = document.getElementById('base_price').value * 0.052938;">Евро</option>
							<option value="4" onselect="document.getElementById('priceTE').value = document.getElementById('base_price').value * 2.621546;">Российский рубль</option>
						</select>

			<p class="preference_description">Manufacturer's recommended price</p>
		</td>
	</tr>
Но работать не хочет. Где я не вижу ошибки? Edited by m_slon (see edit history)
Link to comment
Share on other sites

Во-первых события применяются к select, а не к опциям, а во-вторых это событие называется onChange.

Добавить к опциям атрибут rate с курсом валюты и этот скрипт

$("#base_currency")
  .change(function () {
    $('#priceTE').val($('#priceTE').val()*$("#base_currency option:selected").attr('rate'));
  })
  .change()
Edited by sors (see edit history)
  • Like 1
Link to comment
Share on other sites

Спасибо, поправил поля, а заодно поменял * на /

Теперь у меня он выглядит так:

$("#base_currency").change(function () {
    $('#priceTE').val(ps_round($('#base_price').val() / $("#base_currency option:selected").attr('rate'), 2));
  })
В принципе уже и в таком виде высчитываются нужные цифры, только нужно дополнительно переходить на поле Цена, чтобы остальное тоже пересчиталось. Поправлю потом и этот дефект.

Дальше займусь работой с обновлениями курсов валют и автоматического пересчёта цен.

Edited by m_slon (see edit history)
Link to comment
Share on other sites

×
×
  • Create New...