devel

[Решено] Новая "старая" тема про НДС

Рекомендуемые сообщения

devel    34

Изначально, в чистом opencart, цена товара выводится либо:

1) БЕЗ НДС (например 100р) и ниже С НДС (в примере - 118р), - это если включено отображение цены с НДС, а НДС установлен 18%. 

либо

2) БЕЗ НДС ( в примере 100р)

 

Это удобно, например, для США, где цены в магазине указаны без VAT, а сам налог VAT добавляется к цене на кассе. 

 

В РФ цена товара практически всегда уже включает НДС (если товар облагается НДС), а сумма налога выделяется из итоговой суммы по формуле: НДС = Цена товара * 18/118. Ранее на форуме писали об этом, но решение не найдено (или умалчивается?)

 

Хочется вернуться к этой теме, т.к. для заказчиков юр.лиц размер ндс (и само его наличие) часто играет определяющую роль.

 

Если установить НДС равным 18%, он будет прибавляться к цене товара. Это корень проблемы, т.к. в нашем случае ндс должен вычитаться из цены, и рассчитываться по формуле (см. выше). На форуме найдено несколько решений, в т.ч. устанавливать цены на 18% ниже, а затем прибавлять к ним НДС. Но эти решения неудобны. Правильнее найти файл, в котором происходит подсчет ндс и вместо операции сложения вывести цену с ндс, а в поле tax-text выводить не "Сумма без НДС", а само значение ндс.

 

Например, нужно посчитать:

 

Товар 1

Цена с НДС 100р

НДС (включен в сумму) 15.25р

Итого 100р

 

В шаблоне карточки товара достаточно вывести

Товар 1

Цена 100р

НДС 15.25р

 

Кто подскажет, где происходит расчет налога в opencart? 

www\catalog\model\total\tax.php - это?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
afwollis    1 097

system/library/tax.php

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
devel    34

system/library/tax.php

Благодарю за быстрый ответ! 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
devel    34

А какой физический смысл переменной $amount ?

Вообще, как трактовать $value, $tax-rate, $amount?

Функций много, но смысл их непонятен, без понимания для чего используется переменная.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
devel    34

Оказывается, system/library/tax.php - это только вершина айсберга. Удалось включением/выключением отображения цен с налогом в админке выводить сумму с НДС и без НДС. для этого в tax.php сделаны следующие изменения:

  	public function calculate($value, $tax_class_id, $calculate = true) {
		if ($tax_class_id && $calculate) {
			$amount = $this->getTax($value, $tax_class_id);
				
			return $value - $amount;
		} else {
		      		return $value;
    	}
  	}

и

			if ($tax_rate['type'] == 'F') {
				$amount += $tax_rate['rate'];
			} elseif ($tax_rate['type'] == 'P') {
				$amount += $value * $tax_rate['rate']/(100 + $tax_rate['rate']);
			}

Здесь используются операторы $value, $tax_rate, $amount. По логике, $value - значение (цена товара) до обложения налогом, $tax_rate - налоговая ставка, $amount - рассчетная величина налога.  Если отталкиваться от того, что $value уже включает НДС (в России, например), то налог нужно вычесть $amount из $value Однако, ряд проблем (даже еще не все выявил) ожидают в корзине, счете и т.п.

 

В файлах шаблонов www\catalog\view\theme\default\template\product используются переменные $price и $tax, которые, по логике разработчиков выводят Цену с налогом и Цену без налога. Где и как они связаны с $amount, $tax-rate, $value я пока не нашел.

 

Предполагаю также, что разработчики вложили в понятие $amount смысл аккумулятора всех налогов, а не только НДС. Вобщем, такая внешне простая задача имеет довольно много нюансов. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
devel    34

Я извиняюсь, коллеги!

 

А не изобретаю я тут велосипед, случайно? Вопрос риторический, но неужели все отключили налог в админке, и счастливы? Как тогда обстоят дела с корзиной, счетом, они же добавляют ндс?

 

У меня такое предчуствие, что я не первый пришел к этому вопросу, но все почму-то помалкивают )) 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
devel    34

Правильно ли я понимаю смысл данного тренарного выражения:

 

$tax = $this->currency->format((float)$result['special'] ? $result['special'] : $result['price']);

 

такса = спец. цене (в формате и валюте магазина), если товар иммеет признак спец.цены, иначе такса = значению price

 

??

каков тогда смысл этого:

$price = $this->currency->format($this->tax->calculate($result['price'], $result['tax_class_id'], $this->config->get('config_tax')));

 

и этого:

$special = $this->currency->format($this->tax->calculate($result['special'], $result['tax_class_id'], $this->config->get('config_tax')));

 

Тяжеловато с ООП, когда есть представления только об алгоритмических языках.  

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
devel    34

Задача решена, тему можно закрывать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
RHCk    15

Могу попросить Вас обнародовать решение?:)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
lavlan    2

Присоединяюсь

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
devel    34

Чтобы в карточке товара и каталоге отображалась цена с налогом, а под ним размер налога, делаем следующие изменения:

В файле \system\library\tax.php:

Ищем блок:

public function calculate($value, $tax_class_id, $calculate = true) {
		if ($tax_class_id && $calculate) {
			$amount = $this->getTax($value, $tax_class_id);
			return $value + $amount;
		} else {
      		return $value;
  }
}

Заменяем его на:

public function calculate($value, $tax_class_id, $calculate = true) {
		if ($tax_class_id && $calculate) {
		return $value;	
		} else {
    $amount = $this->getTax($value, $tax_class_id);
		return $value - $amount;
}
}

Смысл этой замены в том, что мы под $value будем  подразумевать стоимость одного товара с учетом ндс (а не наоборот, как задумано разработчиками), и наша задача не прибавить значение налога к сумме, а выделить его из суммы. Под $amount будем подразумевать размер налог (в валюте и формате магазина). Не путать $amount и $tax_rate! Последний – это именно процентная ставка, а $amount – конкретное значение налога для каждого конкретного товара, в рублях в нашем случае. В РФ ставка НДС=18%. Размер налога вычисляется по формуле: Цена товара * Ставку налога /(100+Ставка налога), или Цена товара*18/118. Для исправления формулы налога, находим в файле \system\library\tax.php следующий блок:

if ($tax_rate['type'] == 'F') {
				$amount += $tax_rate['rate'];
			} elseif ($tax_rate['type'] == 'P') {
				$amount += ($value / 100 * $tax_rate['rate']);
			}

И меняем его на:

if ($tax_rate['type'] == 'F') {
				$amount += $tax_rate['rate'];
			} elseif ($tax_rate['type'] == 'P') {
				$amount += ($value * $tax_rate['rate']/ (100 + $tax_rate['rate']));
			}

Если теперь в админке выбрать пункт «Отображать цены с налогом» - «Да», то будет выводится значение $value (которое у нас уже включает НДС). Если выбран чекбокс «Нет» - будет отображаться Цена без НДС (сли это вообще кому-то нужно).

 

Задача №2. Вывести значение размера налога (в рублях) в карточке товара и каталоге, вместо «Цена без НДС».

Каталог.

Для решения этой задачи перейдем к файлу  \catalog\controller\product\category.php. Найдем в нем блок:

if ((float)$result['special']) { 
…..
}

И заменим:

if ((float)$result['special']) {
					$special = $this->currency->format($this->tax->calculate($result['special'], $result['tax_class_id'], $this->config->get('config_tax')));
          $amount = $this->tax->getTax($result['special'], $result['tax_class_id']);
				} else {
					$special = false;
					$amount = $this->tax->getTax($result['price'], $result['tax_class_id']);
				}	
				
				if ($this->config->get('config_tax')) {
					$tax = $this->currency->format((float)($result['special'] ? ($result['special'] - $amount) : ($result['price'] - $amount)));
          $nds = $this->currency->format((float)($result['special'] ? $amount : $amount));
        //  echo 'tax=', $tax, '</br>';
        //  echo 'price=', $result['price']-$amount, '</br>';
        //  echo 'amount=', $amount;
				} else {
					$tax = false;
					$nds = false;
					
				}

Закомменченые строки можно удалить, они для отладки.

Добавим в массив $this->data['products'][] = array() нашу переменную ндс:

'nds'         => $nds

 

Здесь мы обращаемся к методу getTax, который возвращает значение НДС (в рублях), вводим новую переменную $nds, которую получаем из разницы цены с ндс ($price) и цены без ндс ($result[‘price’]). Заодно, корректируем значение переменной $tax, также уменьшая ее на размер налога НДС ($amount), поскольку именно $tax выводится в шаблоне как «цена без НДС». Если этого не сделать, «Цена без НДС» и «Цена» будут равны, что неверно.

Подправим шаблон категории  \catalog\view\theme\default\template\product\category.tpl

Заменим в нем блок:

<?php if ($product['tax']) { ?>
        <br />
        <span class="price-tax"><?php echo $text_tax; ?> <?php echo $product['tax']; ?></span>
        <?php } ?>
На такой:
        <?php if ($product['tax']) { ?>
        <br />
        <span class="price-tax"><?php echo 'В т.ч. НДС:' ?> <?php echo $product['nds']; ?></span>
        <?php } ?>

Я нарочно убрал   <?php echo $product['tax']; ?>, т.к. для меня эта информация бесполезна. Но можно его оставить, сделав еще одной отдельной строкой размер ндс:

 <span class="price-tax"><?php echo $text_tax; ?> <?php echo $product['tax']; ?></br><?php echo 'В т.ч. НДС:' ?> <?php echo $product['nds']; ?></span>

Карточка товара.

Аналогично, открываем файл контроллера \catalog\controller\product\product.php и меняем в нем блок:

if ((float)$product_info['special']) {
….
}

На этот:

if ((float)$product_info['special']) {
				$this->data['special'] = $this->currency->format($this->tax->calculate($product_info['special'], $product_info['tax_class_id'], $this->config->get('config_tax')));
        $amount = $$this->tax->getTax($product_info['special'], $product_info['tax_class_id']);
			} else {
				$this->data['special'] = false;
				$amount = $this->tax->getTax($product_info['price'], $product_info['tax_class_id']);
			}
					
			if ($this->config->get('config_tax')) {
				$this->data['tax'] = $this->currency->format((float)$product_info['special'] ? ($product_info['special'] - $amount) : ($product_info['price'] - $amount));
        $this->data['nds'] = $this->currency->format((float)$product_info['special'] ? $amount : $amount);
			} else {
        $this->data['nds'] = false;
				$this->data['tax'] = false;
			}

Подправим шаблон карточки товара  \catalog\view\theme\default\template\product\product.tpl

Заменим строку:

<span class="price-tax"><?php echo $text_tax; ?> <?php echo $tax; ?></span><br />

На эту:

<span class="price-tax"><?php echo 'В т.ч. НДС:'; ?> <?php echo $nds; ?></span><br />

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
devel    34

Задача №3. Вывести значение цены товара с НДС и отдельно НДС в результат поиска.

Открываем  \catalog\controller\product\search.php

Находим:

if ($this->config->get('config_tax')) {
					$tax = $this->currency->format((float)$result['special'] ? $result['special'] : $result['price']);
				} else {
					$tax = false;
				}

Меняем на :

$amount = $this->currency->format($this->tax->getTax($result['price'], $result['tax_class_id']));
				if ($this->config->get('config_tax')) {
					$tax = $this->currency->format((float)$result['special'] ? ($result['special'] - $amount) : ($result['price'] - $amount));
          $nds = $this->currency->format((float)$price - ($result['special'] ? ($result['special'] - $amount) : ($result['price'] - $amount)));
				} else {
          $nds = false;
					$tax = false;
				}

И добавим в массив $this->data['products'][] = array() нашу переменную ндс:

'nds'         => $nds

Правим шаблон \catalog\view\theme\default\template\product\search.tpl

Меняем строку:

<span class="price-tax"><?php echo $text_tax; ?> <?php echo $product['tax']; ?></span>

На эту:

<span class="price-tax"><?php echo 'В т.ч. НДС:'; ?> <?php echo $product['nds']; ?></span>

Задача №4. Скорректировать значение цены в корзине.

 

 

Чтобы в корзине не добавлялся налог к «Итого», а также правильно отображалась информация в блоке «Х товаров – ХХХХр», в файле \catalog\model\total\tax.php меняем

$total += $value;

на

$total = $total;

 

Задача №5. Корректная цена в счете.

 

Открываем \admin\controller\sale\order.php и дважды в файле заменяем строки :

'price'    => $this->currency->format($product['price'] + ($this->config->get('config_tax') ? $product['tax'] : 0), $order_info['currency_code'], $order_info['currency_value']),
						'total'    => $this->currency->format($product['total'] + ($this->config->get('config_tax') ? ($product['tax'] * $product['quantity']) : 0), $order_info['currency_code'], $order_info['currency_value'])

На эти:

'price'    => $this->currency->format($product['price'], $order_info['currency_code'], $order_info['currency_value']),
'total'    => $this->currency->format($product['total'], $order_info['currency_code'], $order_info['currency_value'])

Со стороны покупателя, в личном кабинете, счет также отображает некорректную сумму. Правим файл \catalog\controller\account\order.php Должно стать так:

'price'    => $this->currency->format($product['price'], $order_info['currency_code'], $order_info['currency_value']),
'total'    => $this->currency->format($product['total'], $order_info['currency_code'], $order_info['currency_value']),

ВСЕ!

 

П.С. Просьба не пинать, т.к. это первый опыт php5 (ООП)

Если есть желающие переделать решение для vqmod - только приветствуется. Проблем с обновлением движка тогда не будет. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
RHCk    15

 

Добавим в массив $this->data['products'][] = array() нашу переменную ндс:

'nds'         => $nds

 

Здесь мы обращаемся к методу getTax, который возвращает значение НДС (в рублях), вводим новую переменную $nds, которую получаем из разницы цены с ндс ($price) и цены без ндс ($result[‘price’]). Заодно, корректируем значение переменной $tax, также уменьшая ее на размер налога НДС ($amount), поскольку именно $tax выводится в шаблоне как «цена без НДС». Если этого не сделать, «Цена без НДС» и «Цена» будут равны, что неверно.

 

Это описание производимых действий или это нужно сделать дополнительно помимо замены кода?

 

Сделал все замены до описания изменений в Карточке товара - результат следующий:

В каталоге под ценой товара - в т.ч. НДС: Notice: Undefined index: nds in/***/catalog/view/theme/default/template/product/category.tpl on line 86

 

Строка 86:

<span class="price-tax"><?php echo 'в т.ч. НДС:' ?> <?php echo $product['nds']; ?></span>

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
devel    34

Добавьте переменную $nds в массив $this->data['products'][] = array(

.......

.......

)

 

вот так должно быть:

				$this->data['products'][] = array(
					'product_id'  => $result['product_id'],
					'thumb'       => $image,
					'name'        => $result['name'],
					'description' => utf8_substr(strip_tags(html_entity_decode($result['description'], ENT_QUOTES, 'UTF-8')), 0, 100) . '..',
					'price'       => $price,
					'special'     => $special,
					'tax'         => $tax,
					'rating'      => $result['rating'],
					'reviews'     => sprintf($this->language->get('text_reviews'), (int)$result['reviews']),
					'href'        => $this->url->link('product/product', 'path=' . $this->request->get['path'] . '&product_id=' . $result['product_id'] . $url),
					'nds'         => $nds
				);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
RHCk    15

Спасибо за подсказку! Ошибка пропала, НДС показывается равным нулю, медленно иду дальше:)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
RHCk    15

Подошел к Задаче 4. Результат предыдущих деяний:

- В каталоге НДС равен нулю

- В карточке НДС равен нулю

- В поиске НДС равен минус цене (т.е. цена 200, НДС -200)

 

Куда копать? :)

 

Прошу пардона, в файле product.php на автомате добавил переменную nds в массив, в карточке товара появилась ошибка, переменную убрал - исчез отрицательный НДС в поиске, теперь он везде равен нулю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
devel    34

Значит у вас $amount равен $price. Где-то в контроллере library\tax.php забыли $amount подправить.

Вообще, надо понимать, что мы принимаем за :

$value в ф-ии calculate - цена с НДС

$amount - НДС

и в шаблоне:

$price - цена с НДС

$tax - цена без НДС

 

Еще вариант - в админке должно быть Система-Настройки-Опции:

- Отображать цены с налогом: Да

- Проверка номера налога: Нет

 

Система-Локализация-Налоги-Налоговые ставки:

Название: НДС

Ставка: 18

Тип: процент

Группа покупателей: основная

Геозона: РФ

 

Ставьте в коде отладочные строки, типа:

echo '$amount = ', $amount, '</br>';

Помогает разобраться на каком этапе у вас ошибка в рассчетах.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
RHCk    15

 Всё получилось! Сам не осилил, попросил помощи у более опытного товарища, но дело оказалось не в сложности кода, а скорее в моей невнимательности, после указания геозоны налоги стали рассчитываться :)

 

 Классы налогов и ставки сделал как на скриншотах, поэкспериментировал и оставил в таком виде. Удобно, потому как НДС может быть и 10% (ст.164 НК РФ), а в таком виде виден налог при добавлении товара, и в Корзине покупателя.

 

 С разрешения автора могу выложить файлы с изменениями, делалось для Opencart v1.5.6.

 

 Прошу разработчиков ocStore присмотреться к этому решению и по возможности добавить его в дистрибутив, потому как этот вариант рассчитан для нашей местности :)

 

P.S. Пока не буду создавать новую тему, просто спрошу, в админке, при попытке изменить заказ покупателя, не сталкивались ли вы с синтаксической ошибкой при нажатии Добавить товар?

Классы налогов.jpg

Ставки налогов.jpg

post-674130-0-16873700-1383765500_thumb.jpg

post-674130-0-52122300-1383765500_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
devel    34

 С разрешения автора могу выложить файлы с изменениями, делалось для Opencart v1.5.6.

Не возражаю. Был удивлен, что за столько лет существования движка это не было сделано (или было?  ;) )

Решение ошибки, о которой вы упоминаете в постскрипте, я нашел пару дней назад, и создал отдельную тему:

Не вникал в суть решения. На вскидку, - не инициализированна переменная. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
RHCk    15

Файлы разложены по папкам согласно структуре Opencart. Достаточно скопировать с заменой содержимое папки Upload в папку сайта.

 

2devel

Ещё раз спасибо за помощь и подсказку :)

 

07.11.2013 12:30 перезалил файл

NDS_for_Opencart_v1.5.6.zip

NDS_for_Opencart_v1.5.6.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
vitek9603    2

Кто может за соответсвующую плату внести данные изменения? 

или может vqmod  есть? 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
alnem    4

catalog/model/checkout/order.php

Еще один файл, где надо внести изменения по аналогии с \catalog\controller\account\order.php , чтобы письмо клиенту приходило с правильными цифрами. Письмо админу о заказе тоже там же формируется.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
devel    34

catalog/model/checkout/order.php

Еще один файл, где надо внести изменения по аналогии с \catalog\controller\account\order.php , чтобы письмо клиенту приходило с правильными цифрами. Письмо админу о заказе тоже там же формируется.

Все верно, Дополнение по поводу письма не учел. У себя поправил, Кто ранее пользовался полным решением - рекомендуется добавить изменения, озвученные alnem

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
solenka    0

Добрый день, а для версии 1.5.4 тоже сработает? 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
alesco    0

Версия OpenCart 1.5.5.2

Сделал все пошагово как указано выше, НДС считает 15,25%, вместо указанных 18%.

При добавлении в переменной 'nds' => $nds  в массив $this->data['products'][] = array(

 

выдает ошибку

 

Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING, expecting ')' in Z:\home\localhost\www\domen.ru\catalog\controller\product\category.php on line 283

 

В чем может быть косяк?

 

А может у кого есть готовая сборка с исправлениями под  OpenCart 1.5.5.2 ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти


  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу