При работе с конфигурацией 1С:Управление торговлей 11.1, особенно если она имеет многочисленные доработки, мы можем столкнуться с необходимостью массового изменения реквизитов, таких как ставка НДС, у элементов справочника «Номенклатура». Часто типовые механизмы, вроде «Группового изменения реквизитов», оказываются неработоспособными, а поле для ручного изменения ставки НДС на форме элемента справочника может быть заблокировано. В такой ситуации возникает потребность в программном решении. Для разблокировки этого поля можно применить расширение для изменения ставки НДС через групповое изменение реквизитов.
Рассмотрим подробно, как мы можем решить эту задачу, избегая распространенных ошибок и используя специфические особенности платформы 1С:Предприятие.
Прежде чем перейти к решению, выясним, почему мы сталкиваемся с такими сложностями:
Перечисления.СтавкиНДС. Если его нет, нам потребуется его создать, что может потребовать обновления конфигурации или ручного вмешательства.Мы будем использовать программный код для обхода всех элементов нужной группы справочника и принудительного изменения ставки НДС. Рассмотрим процесс по шагам, с учетом возможных ошибок и их исправлений.
Прежде всего, нам необходимо найти целевую группу справочника и определить значение ставки НДС, на которое мы хотим изменить. Важно корректно указать желаемую ставку.
В первоначальной попытке могла быть допущена ошибка, когда вместо Перечисления.СтавкиНДС.Ставка20 случайно указывалось Перечисления.СтавкиНДС.БезНДС. Мы должны всегда проверять, какое значение перечисления мы используем.
Рассмотрим пример правильной инициализации:
Группа = Справочники.Номенклатура.НайтиПоНаименованию("ПрограммноеОбеспечение");
Если Группа = Неопределено Тогда
Сообщить("Группа номенклатуры 'ПрограммноеОбеспечение' не найдена!");
Возврат;
КонецЕсли;
НДС20 = Перечисления.СтавкиНДС.Ставка20; // Правильно указываем целевую ставку НДС
Запрос = Новый Запрос;
Мы всегда должны проверять, найдена ли группа, чтобы избежать ошибок при выполнении запроса.
Далее мы формируем запрос, который выберет все элементы номенклатуры, принадлежащие нашей группе, не являющиеся группами сами по себе и имеющие ставку НДС, отличную от 20%.
Запрос.Текст = "ВЫБРАТЬ
| Номенклатура.Ссылка,
| Номенклатура.ЭтоГруппа,
| Номенклатура.Родитель,
| Номенклатура.Наименование,
| Номенклатура.СтавкаНДС
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Родитель = &Группа
| И Номенклатура.ЭтоГруппа = &Ложь
| И Номенклатура.СтавкаНДС <> &НДС20";
Запрос.УстановитьПараметр("Группа", Группа);
Запрос.УстановитьПараметр("Ложь", Ложь);
Запрос.УстановитьПараметр("НДС20", НДС20);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Этот запрос позволяет нам получить только те элементы, которые действительно нуждаются в изменении, что оптимизирует процесс и избегает ненужных записей.
Это самый критичный шаг. Распространенной ошибкой является многократный вызов ПолучитьОбъект() в цикле. Каждый вызов Выборка.Ссылка.ПолучитьОбъект() создает новый экземпляр объекта из базы данных. Если мы изменяем реквизит одного объекта, а затем пытаемся записать другой, наши изменения не сохранятся.
Мы должны получить объект один раз, внести все необходимые изменения, а затем один раз записать этот же объект. Кроме того, для обхода блокировок и проверок, которые могут быть установлены в конфигурации (особенно в доработанных), мы можем использовать флаг ОбменДанными.Загрузка = Истина.
Этот флаг сигнализирует системе, что данные загружаются в режиме обмена, что часто отключает часть проверок и бизнес-логики, которые могли бы препятствовать записи. После записи объекта мы всегда должны вернуть флаг в исходное состояние (Ложь), чтобы не повлиять на дальнейшую работу системы.
Рассмотрим исправленный и рекомендуемый подход:
// Включаем режим обмена данными, чтобы обойти возможные блокировки и проверки
ОбменДанными.Загрузка = Истина;
Пока Выборка.Следующий() Цикл
Попытка
ОбъектНоменклатура = Выборка.Ссылка.ПолучитьОбъект(); // Получаем объект один раз
ОбъектНоменклатура.СтавкаНДС = НДС20; // Изменяем реквизит
ОбъектНоменклатура.Записать(); // Записываем измененный объект
Сообщить("Успешно изменена ставка НДС для номенклатуры: " + ОбъектНоменклатура.Наименование);
Исключение Как Искл
Сообщить("Ошибка при изменении ставки НДС для номенклатуры " + Выборка.Наименование + ": " + Искл.Описание);
КонецПопытки;
КонецЦикла;
// Выключаем режим обмена данными
ОбменДанными.Загрузка = Ложь;
Сообщить("Процесс изменения ставок НДС завершен.");
Оборачивание записи в блок Попытка...Исключение позволяет нам обрабатывать возможные ошибки для каждого элемента по отдельности и продолжить выполнение обработки, даже если с одним из элементов возникли проблемы. Это очень полезно при массовых изменениях.
Соберем все шаги в единый код, который можно использовать как внешнюю обработку или часть модуля:
&НаКлиенте
Процедура ВыполнитьИзменениеСтавкиНДС(Команда)
// Необходимо подтверждение пользователя перед выполнением критичных операций
Если Не Вопрос("Вы уверены, что хотите изменить ставку НДС для всех элементов выбранной группы на 20%?", РежимДиалогаВопрос.ДаНет, 60) = КодВозвратаДиалога.Да Тогда
Возврат;
КонецЕсли;
// Вызов серверной процедуры
ВыполнитьИзменениеСтавкиНДСНаСервере();
КонецПроцедуры
&НаСервере
Процедура ВыполнитьИзменениеСтавкиНДСНаСервере()
Сообщить("Начинаем процесс изменения ставок НДС...", СтатусСообщения.Информация);
// Шаг 1: Инициализация параметров запроса
Группа = Справочники.Номенклатура.НайтиПоНаименованию("ПрограммноеОбеспечение");
Если Группа = Неопределено Тогда
Сообщить("Группа номенклатуры 'ПрограммноеОбеспечение' не найдена! Проверьте наименование.", СтатусСообщения.Ошибка);
Возврат;
КонецЕсли;
// Убедимся, что ставка 20% существует в перечислениях
Если Не Перечисления.СтавкиНДС.ЗначениеДоступно("Ставка20") Тогда
Сообщить("Внимание: Ставка НДС 20% отсутствует в списке доступных перечислений!
|Возможно, требуется обновление конфигурации или ручное добавление значения.
|Изменение ставки невозможно.", СтатусСообщения.Ошибка);
Возврат;
КонецЕсли;
НДС20 = Перечисления.СтавкиНДС.Ставка20;
Запрос = Новый Запрос;
// Шаг 2: Формирование и выполнение запроса
Запрос.Текст = "ВЫБРАТЬ
| Номенклатура.Ссылка,
| Номенклатура.ЭтоГруппа,
| Номенклатура.Родитель,
| Номенклатура.Наименование,
| Номенклатура.СтавкаНДС
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Родитель В ИЕРАРХИИ (&Группа)
| И Номенклатура.ЭтоГруппа = &Ложь
| И Номенклатура.СтавкаНДС <> &НДС20"; // Исключаем уже установленные ставки
Запрос.УстановитьПараметр("Группа", Группа);
Запрос.УстановитьПараметр("Ложь", Ложь);
Запрос.УстановитьПараметр("НДС20", НДС20);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
// Шаг 3: Корректное изменение и запись объекта
ПересчитаноЭлементов = 0;
// Включаем режим обмена данными, чтобы обойти возможные блокировки и проверки
ОбменДанными.Загрузка = Истина;
Пока Выборка.Следующий() Цикл
Попытка
ОбъектНоменклатура = Выборка.Ссылка.ПолучитьОбъект();
// Дополнительная проверка, чтобы не записывать лишний раз, если СтавкаНДС поменялась между запросом и получением объекта
Если ОбъектНоменклатура.СтавкаНДС <> НДС20 Тогда
ОбъектНоменклатура.СтавкаНДС = НДС20;
ОбъектНоменклатура.Записать();
ПересчитаноЭлементов = ПересчитаноЭлементов + 1;
Сообщить("Успешно изменена ставка НДС для номенклатуры: " + ОбъектНоменклатура.Наименование, СтатусСообщения.Информация);
КонецЕсли;
Исключение Как Искл
Сообщить("Ошибка при изменении ставки НДС для номенклатуры " + Выборка.Наименование + ": " + Искл.Описание, СтатусСообщения.Ошибка);
КонецПопытки;
КонецЦикла;
// Выключаем режим обмена данными
ОбменДанными.Загрузка = Ложь;
Сообщить("Процесс изменения ставок НДС завершен. Изменено элементов: " + ПересчитаноЭлементов, СтатусСообщения.Информация);
КонецПроцедуры
В этом примере мы добавили проверку Перечисления.СтавкиНДС.ЗначениеДоступно("Ставка20"), чтобы убедиться в наличии необходимого значения НДС перед началом обработки. Также запрос был изменен с Родитель = &Группа на Родитель В ИЕРАРХИИ (&Группа), чтобы обрабатывать все элементы внутри группы, включая вложенные подгруппы. Это обеспечивает более полное покрытие, если такая иерархия присутствует.
Хотя в нашем случае типовые обработки не сработали из-за доработок, полезно знать о них:
Использование программного кода с учетом всех перечисленных нюансов позволяет нам эффективно решить задачу массового изменения ставки НДС в 1С:Управление торговлей 11.1, особенно в условиях доработанной конфигурации и заблокированных полей. Для решения этой задачи без программирования можно использовать обработку для массового изменения ставки НДС у номенклатуры.