Добавление новых ставок НДС в УТ 11.4 с ККМ

Клиенту, занимающемуся оптово-розничной торговлей, нужно добавить ставки в УТ 11.4. Можно было бы обновиться до последнего релиза УТ 11.5, но это объемно, потому что сделано много доработок, хотя и в расширениях, но все же. Решено обновлять текущую базу.

1. Доработки в конфигурации

НДС20 встречается 369 раз:

Добавляем значения ставок:

Изменения помечал маркером //Осипов НДС-2026 26.01.03

Модули МенеджерОборудованияВызовСервера, МенеджерОборудованияКлиентСервер — много копипасты, потому что ставки там прописаны напрямую в переменных, проще копировать код, что-то вроде:

//Осипов НДС-2026 26.01.03 +++
Если СуммаПозицийНДС5 > 0 Тогда
	ЗначениеНДС = ?(СуммаНДС5 > 0, СуммаНДС5, СуммаПозицийНДС5 / 105 * 5);
	Текст = Текст + ВыстроитьПоля(НСтр("ru=' СУММА НДС 5%'"), "=" + Формат(ЗначениеНДС, ФорматЧисла), ШиринаСтроки) + Символы.ПС;
КонецЕсли;                    
Если СуммаПозицийНДС7 > 0 Тогда
	ЗначениеНДС = ?(СуммаНДС7 > 0, СуммаНДС7, СуммаПозицийНДС7 / 107 * 7);
	Текст = Текст + ВыстроитьПоля(НСтр("ru=' СУММА НДС 7%'"), "=" + Формат(ЗначениеНДС, ФорматЧисла), ШиринаСтроки) + Символы.ПС;
КонецЕсли;                    
Если СуммаПозицийНДС22 > 0 Тогда
	ЗначениеНДС = ?(СуммаНДС22 > 0, СуммаНДС22, СуммаПозицийНДС22 / 122 * 22);
	Текст = Текст + ВыстроитьПоля(НСтр("ru=' СУММА НДС 22%'"), "=" + Формат(ЗначениеНДС, ФорматЧисла), ШиринаСтроки) + Символы.ПС;
КонецЕсли;                    
Если СуммаПозицийНДС105 > 0 Тогда
	ЗначениеНДС = ?(СуммаНДС105 > 0, СуммаНДС105, СуммаПозицийНДС105 / 105 * 5);
	Текст = Текст + ВыстроитьПоля(НСтр("ru=' СУММА НДС 5/105%'"), "=" + Формат(ЗначениеНДС, ФорматЧисла), ШиринаСтроки) + Символы.ПС;
КонецЕсли;
Если СуммаПозицийНДС107 > 0 Тогда
	ЗначениеНДС = ?(СуммаНДС107 > 0, СуммаНДС107, СуммаПозицийНДС107 / 107 * 5);
	Текст = Текст + ВыстроитьПоля(НСтр("ru=' СУММА НДС 7/107%'"), "=" + Формат(ЗначениеНДС, ФорматЧисла), ШиринаСтроки) + Символы.ПС;
КонецЕсли;
Если СуммаПозицийНДС122 > 0 Тогда
	ЗначениеНДС = ?(СуммаНДС122 > 0, СуммаНДС122, СуммаПозицийНДС122 / 122 * 5);
	Текст = Текст + ВыстроитьПоля(НСтр("ru=' СУММА НДС 22/122%'"), "=" + Формат(ЗначениеНДС, ФорматЧисла), ШиринаСтроки) + Символы.ПС;
КонецЕсли;
//---

Но особо не сильно менял, решил, что остальное поменяю позже, в первую очередь надо сделать доработки по пробитию чеков.

2. Первые тесты 1С и оборудования

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

Общая политика учета не подходит, т.к. тогда не пробиваются чеки из-за другой СНО.

Раньше УСН была без НДС. Пришлось добавлять галочку дор_УСНСНДС в справочник УчетныеПолитикиОрганизаций.

И учитывать ее в УчетНДСЛокализация.ДополнитьПараметрыУчетаОрганизации:

//Осипов НДС-2026 26.01.03	
Если ПараметрыУчетнойПолитики.дор_УСНСНДС Тогда
	ПараметрыУчета.ОсновноеНалогообложениеНДСПродажи = Перечисления.ТипыНалогообложенияНДС.ПродажаОблагаетсяНДС;
КонецЕсли;

Драйвет торгового оборудования был старый 10.8.1.0, обновил на 10.10.8.0:

В чеке появилась ставка НДС, но почему-то не рассчитывалась сумма НДС, решил оставить пока так и разобраться позже.

3. Исправление ошибки СНО

Однако при печати чека возникла ошибка:

При печати чека произошла ошибка.
Чек не напечатан на фискальном устройстве.
Дополнительное описание:
ККТ не зарегистрирована с указанной системой налогообложения.

Пришлось запускать конфигуратор с отладкой на компьютере с кассой, чтобы разобраться с проблемой.

Ошибка возникает в ФорматноЛогическийКонтрольВызовСервера.ВыполненаПроверкаОбязательностиИПравильностиЗаполненияТэгов:

В параметрах чека код системы налогообложения неправильно 5 (Патент), а в кассе правильно 1 (УСН доход):

Оказалось, там застряли старые параметры регистрации устройства (старая СНО — патент).

Чтобы их обновить, нужно выбрать пункт «Изменение параметров регистрации», при этом дальше изменять не надо, при нажатии на кнопку параметры считаются и обновятся.

Чек пробился но со ставкой 0%:

  <Positions>
    <FiscalString Name="Резка"
        Quantity="1"
        PriceWithDiscount="10"
        AmountWithDiscount="10"
        DiscountAmount="0"
        Department="1"
        VATRate="0"
        VATAmount=""
        PaymentMethod="4"
        CalculationSubject="4">
      <AgentData/>
      <VendorData/>
    </FiscalString>
  </Positions>

РешиVATRate

Чтобы не допускать 0% ставки НДС, делал чек на возврат.

Обратил внимание что ставка НДС равна нулю:

Сделал точку останова в МенеджерОборудованияКлиент.НачатьВыполнениеКоманды_ВыбратьУстройствоЗавершение:

Чтобы не делать постоянно возвраты. Просто очищать в табло Параметры и фискализация чека возвращает ошибку.

Пропустил функцию УчетНДСУПКлиентСервер.ПолучитьСтавкуНДС, а она вызывалась как раз для расчета ставки НДС при фискализации и в прочих случаях:

Функция ПолучитьСтавкуНДС(СтавкаНДС) Экспорт
	
	Если СтавкаНДС = ПредопределенноеЗначение("Перечисление.СтавкиНДС.НДС10")
		Или СтавкаНДС = ПредопределенноеЗначение("Перечисление.СтавкиНДС.НДС10_110") Тогда
		Возврат 10;
	ИначеЕсли СтавкаНДС = ПредопределенноеЗначение("Перечисление.СтавкиНДС.НДС18")
		Или СтавкаНДС = ПредопределенноеЗначение("Перечисление.СтавкиНДС.НДС18_118") Тогда
		Возврат 18;
	ИначеЕсли СтавкаНДС = ПредопределенноеЗначение("Перечисление.СтавкиНДС.НДС20")
		Или СтавкаНДС = ПредопределенноеЗначение("Перечисление.СтавкиНДС.НДС20_120") Тогда
		Возврат 20;
		//Осипов НДС-2026 26.01.03 +++
	ИначеЕсли СтавкаНДС = ПредопределенноеЗначение("Перечисление.СтавкиНДС.НДС5") ИЛИ
		СтавкаНДС = ПредопределенноеЗначение("Перечисление.СтавкиНДС.НДС5_105") 
		Тогда
		Возврат 5;    
	ИначеЕсли СтавкаНДС = ПредопределенноеЗначение("Перечисление.СтавкиНДС.НДС7") ИЛИ
		СтавкаНДС = ПредопределенноеЗначение("Перечисление.СтавкиНДС.НДС7_107") 
		Тогда
		Возврат 7;    
	ИначеЕсли СтавкаНДС = ПредопределенноеЗначение("Перечисление.СтавкиНДС.НДС22") ИЛИ
		СтавкаНДС = ПредопределенноеЗначение("Перечисление.СтавкиНДС.НДС22_122") 
		Тогда
		Возврат 22;    //---
	Иначе
		Возврат 0;
	КонецЕсли;
	
КонецФункции

При этом пришлось обновлять конфгирацию на сервере, с локального компьютера это делалось очень медленно.

4. Обновление драйвера ККМ в 1С

Далее при пробитии чека возникла уже знакомая мне ошибка:

При печати чека произошла ошибка.
Чек не напечатан на фискальном устройстве.
Дополнительное описание:
При выполнении операции произошла ошибка: Некорректное значение поля "items[0].tax.type" ()

Она связана с тем, что драйвер не знает ставку НДС 5%.

Проверил в отладчике в МенеджерОборудованияВызовСервера.СформироватьXMLПакетДляФискализацияЧека, что сюда действительно приходит ставка НДС 5%:

Значит, проблема в драйвере ККМ, который не знает ничего про ставку 5%.

Заходим в справочник Драйверы оборудования e1cib/list/Справочник.ДрайверыОборудования. Нажимаем «Добавить новый драйвер из файла». Я выгрузил рабочий драйвер из УТ 11.5 в файл ДрайверАТОЛККТ54ФЗ107X_ru.zip, его и выбираю:

Дал ему говорящее наименование «АТОЛ:ККТ с передачей данных в ОФД 10.x НДС 5% 2026»:

Правда, новый драйвер писал, что его версия отличается, но я это игнорирую:

Чек пробился, но у него по-прежнему нулевая сумма НДС, ну это идет из чека, там сумма НДС не вычисляется почему-то:

  <Positions>
    <FiscalString Name="Резка"
        Quantity="1"
        PriceWithDiscount="10"
        AmountWithDiscount="10"
        DiscountAmount="0"
        Department="1"
        VATRate="5"
        VATAmount=""
        PaymentMethod="4"
        CalculationSubject="4">
      <AgentData/>
      <VendorData/>
    </FiscalString>

5. Пересчет суммы НДС в РМК

Осталось добиться, чтобы пересчитывалась сумма НДС в РМК.

Оказалось, что после поправки расчета суммы НДС по ставке при смене количества сумма НДС рассчитывается, а при смене цены нет. Оказалось, что в типовой УТ нет смены цены и там были сделаны доработки, вот я прямо туда и прописал вызов перерасчета ставки НДС:

&НаКлиенте
Процедура Расш70_ТоварыЦенаПриИзмененииПеред(Элемент)
		ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;	
	СтруктураДействий = Новый Структура;
	ДобавитьВСтруктуруДействияПриИзмененииЦены(СтруктураДействий,Объект);
	
	//Осипов НДС-2026 26.01.03 Нужно пересчитываь сумму НДС при изменении цены
	СтруктураДействий.Вставить("ПересчитатьСуммуНДС", ОбработкаТабличнойЧастиКлиентСервер.ПараметрыПересчетаСуммыНДСВСтрокеТЧ(Объект));
	ОбработкаТабличнойЧастиКлиент.ОбработатьСтрокуТЧ(ТекущаяСтрока, СтруктураДействий, КэшированныеЗначения);
	
	ПересчитатьДокументНаКлиенте();
КонецПроцедур

При смене цены сумма НДС стала перерасчитываться:

Правильность суммы было считать лень, попросил ИИ:

Пробил чек, но там по-прежнему была нулевая сумма НДС. Хотя сумма НДС в табличной части чека не нулевая:

Конфигуратор отлаживал только на сервере, а массив позиций чеков формировался где-то на клиенте. Но я сформировал ошибку и увидел примерный путь:

Значение не является значением объектного типа (ЗаписатьАтрибут)
{ОбщийМодуль.МенеджерОборудованияВызовСервера.Модуль(3134)}:ЗаписьXML.ЗаписатьАтрибут("VATRate", XMLСтрока(ЗначениеСтавкаНДС)); // Ставка НДС
{ОбщийМодуль.МенеджерОборудованияВызовСервера.Модуль(4003)}:МенеджерОборудованияВызовСервера.СформироватьXMLПакетДляФискализацияЧека(ОбщиеПараметры, ПараметрыФискализации);
{ОбщийМодуль.ПодключаемоеОборудованиеУниверсальныйДрайверКлиент.Модуль(1208)}:ПараметрыФискализации = МенеджерОборудованияВызовСервера.ПодготовитьДанныеФискализацииЧека(ВходныеПараметры, ПараметрыПодключения);
{ОбщийМодуль.ПодключаемоеОборудованиеУниверсальныйДрайверКлиент.Модуль(256)}:Результат = ФискализацияЧека(ОбъектДрайвера, Параметры, ПараметрыПодключения, ВходныеПараметры, ВыходныеПараметры);
{ОбщийМодуль.МенеджерОборудованияКлиент.Модуль(2909)}:Результат = ОбработчикДрайвераМодуль.ВыполнитьКоманду(ПараметрыВыполнения.Команда, ПараметрыВыполнения.ВходныеПараметры,
{Документ.ЧекККМ.Форма.ФормаДокументаРМК.Форма(1855)}:ВыполнитьОбработкуОповещения(ПараметрыВыполнения.ОповещениеПродолжения, ПараметрыВыполнения);
{ОбщийМодуль.МенеджерОборудованияКлиент.Модуль(2798)}:ВыполнитьОбработкуОповещения(Параметры.ОповещениеПослеОткрытииЧека, ПараметрыВыполнения);
{ОбщийМодуль.МенеджерОборудованияКлиент.Модуль(1948)}:НачатьВыполнениеКомандыПечатиЧека(ОписаниеОповещения, Параметры.ИдентификаторУстройства, ВыполняемаяКоманда, Параметры, Параметры.ВходныеПараметры);
{ОбщийМодуль.МенеджерОборудованияКлиент.Модуль(601)}:ВыполнитьОбработкуОповещения(ОповещениеПриПодключении, РезультатВыполнения);
{ОбщийМодуль.МенеджерОборудованияКлиент.Модуль(467)}:НачатьПодключениеОборудования(ОповещениеПриПодключении, ИдентификаторКлиента, , ИдентификаторУстройства);
{ОбщийМодуль.МенеджерОборудованияКлиент.Модуль(1888)}:НачатьПодключениеОборудованиеПоИдентификатору(ОписаниеОповещения, Параметры.УникальныйИдентификатор, ИдентификаторУстройства);
{ОбщийМодуль.МенеджерОборудованияКлиент.Модуль(2339)}:НачатьВыполнениеКомандыВыбратьУстройствоЗавершение(ИдентификаторУстройства, Контекст); {Документ.ЧекККМ.Форма.ФормаДокументаРМК.Форма(1810)}:МенеджерОборудованияКлиент.НачатьФискализациюЧекаНаФискальномУстройстве( {Документ.ЧекККМ.Форма.ФормаДокументаРМК.Форма(4614)}:ВыполнитьОбработкуОповещения(ОповещениеПриЗавершении, Истина); {РасширениеДляККМv2 Документ.ЧекККМ.Форма.ФормаДокументаРМК.Форма(135)}:НСтр("ru = 'Перед выполнением операции пробития чека не удалось провести документ.'")); {Доработки Документ.ЧекККМ.Форма.ФормаДокументаРМК.Форма(804)}:ПробитьЧек();
{Документ.ЧекККМ.Форма.ФормаДокументаРМК.Форма(4179)}:ОбработатьДобавлениеОплаты(ДополнительныеПараметры);
{Документ.ЧекККМ.Форма.ФормаСмешаннойОплаты.Форма(325)}:Закрыть(РезультатОплаты);

Пришлось отлаживать на эмуляторе ККМ, хотя он у меня и не работал, но я нашел, где формируются позиции ФормаДокументаРМК.ПараметрыОперацииФискализацииЧека:

Пришлось прописывать код по установке суммы НДС в ФормаДокументаРМК.ДанныеДляПробитияЧека:

В отладчике увидел, что это сработало:

Странно, получается в типовой УТ НДС в чек не подставляется, раз пришлось исправлять эту ошибку?

В XML увидел ставку НДС, в представлении нет:

  <Positions>
    <FiscalString Name="Резка"
        Quantity="1"
        PriceWithDiscount="10"
        AmountWithDiscount="10"
        DiscountAmount="0"
        Department="1"
        VATRate="5"
        VATAmount="0.48"
        PaymentMethod="4"
        CalculationSubject="4">
      <AgentData/>
      <VendorData/>
    </FiscalString>
  </Positions>

Но решил попросить печатную форму чека или ОФД, может 1С просто так отрисовывает представление чеков с НДС. В ОФД выглядит прилично:

6. Установка ставок НДС 5%

К счастью, клиент торгует товаром только по обычной ставке НДС (20%), не пониженной (10%). Поэтому везде проставляю у товаров ставку 5% с помощью групповой обработки Андрея Волина:

В настройках указываю важное, чтобы не было проблем с обработкой:

Предупредил клиента, чтобы у новых товаров ставили 5%. Поэтому проставляю ставку НДС 5% у видов номенклатуры:

7. Проблема с кодом товара

При пробитии некоторых товаров (без штрих-кода) возникала ошибка:

При печати чека произошла ошибка.
Чек не напечатан на фискальном устройстве.
Дополнительное описание:
При выполнении операции произошла ошибка:
Неподдерживаемый тип кода товара

Нашел решение на инфостарте, проверил в модуле МенеджерОборудованияВызовСервера.ЗаписатьДанныеКодаТоварнойНоменклатуры что записывается в тег GoodCodeData:

		Если НЕ ПустаяСтрока(Позиция.КодВидаНоменклатурнойКлассификации) Тогда
			ДанныеКодаТовара = МенеджерОборудованияМаркировкаКлиентСервер.РазобратьШтриховойКодТовара(Позиция.КодВидаНоменклатурнойКлассификации);
			РеквизитКодаТовара = ДанныеКодаТовара.РеквизитКодаТовара;
		Иначе
			РеквизитКодаТовара = ДанныеКодаТоварнойНоменклатуры.РеквизитКодаТовара;
			// Если реквизит кода товара (1162) не передается в готовом виде сформируем его из штрихкода
			Если ПустаяСтрока(РеквизитКодаТовара) Тогда
				ДанныеКодаТовара = МенеджерОборудованияМаркировкаКлиентСервер.РазобратьШтриховойКодТовара(Позиция.Штрихкод);
				РеквизитКодаТовара = ДанныеКодаТовара.РеквизитКодаТовара;
			КонецЕсли;
		КонецЕсли;
		
		// Если первые 2 байта значения кода товара имеют значения "00h00h" в автономном режиме реквизит не включается.
		Если ПараметрыФискализации.АвтономныйРежим И Лев(РеквизитКодаТовара, 2) = "AA" Тогда
			Возврат;
		КонецЕсли;
		// Реквизит кода товара (1162) для стандарта 3.2 и выше в ККТ передается в готовом виде.
		Если НЕ ПустаяСтрока(РеквизитКодаТовара) Тогда
			ЗаписьXML.ЗаписатьНачалоЭлемента("GoodCodeData");
			ЗаписьXML.ЗаписатьАтрибут("MarkingCode", XMLСтрока(РеквизитКодаТовара));
			ЗаписьXML.ЗаписатьКонецЭлемента();
		КонецЕсли;

Если я добавлял внутренний штрих-код с префиксом 22, записывало что-то вроде двоичного значения штрих-кода: RQ0B1lFiKGk=.

У клиента пока что нет маркировки, так что я временно отключил запись этого реквизита.

Дальнейшие доработки

Далее нужно вернуть суммы НДС в реализации, решать вопрос со счет-фактурами и т.п., т.е. обработать уже контур оптовой торговли.

Выводы

Думаю, это обновление не надолго спасет клиента, может еще на год. Потом все же придется переходить на новую УТ. Слишком много слабых мест — от логики 1С, до библиотеки подключаемого оборудования и драйверов. Но годик простоит, если не будет существенных изменений в законах.

Среда: УТ 11.4.13.46 Объем: 6 час.