При разработке бизнес-логики в 1С часто возникает задача проверить значения дополнительных реквизитов (доп. реквизитов) номенклатуры во время проведения документа и при необходимости отменить проведение (установить параметр Отказ = Истина). Рассмотрим, как правильно реализовать такую проверку в общем модуле через подписку на событие ОбработкаПроведения.
Проанализируем частые ошибки, с которыми сталкиваются разработчики при написании подобной проверки:
Источник.Товары[0].Номенклатура.ДополнительныеРеквизиты работает медленно и не учитывает все строки документа.ДополнительныеРеквизиты справочника Номенклатура поле Свойство хранит ссылку на объект плана видов характеристик, а само значение флага или элемента находится в поле Значение. Поэтому проверка вида Строка.Свойство = Истина не вернет корректного результата.ОбщегоНазначенияКлиентСервер.СообщитьПользователю является процедурой, а не функцией. Присваивать результат ее работы переменной не следует, так как это вызовет ошибку выполнения.Если задача заключается исключительно в том, чтобы отменить проведение документа при наличии в табличной части хотя бы одной позицией номенклатуры с установленным доп. реквизитом, наиболее эффективным решением будет использование запроса к базе данных.
Рассмотрим универсальный код для общего модуля, который подходит для любых документов с табличной частью Товары:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Истина КАК НаличиеНоменклатурыСЗапретом
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК НоменклатураДополнительныеРеквизиты
| ПО РеализацияТоваровУслугТовары.Номенклатура = НоменклатураДополнительныеРеквизиты.Ссылка
| И (НоменклатураДополнительныеРеквизиты.Свойство = &Свойство)
| И (НоменклатураДополнительныеРеквизиты.Значение = ИСТИНА)
|ГДЕ
| РеализацияТоваровУслугТовары.Ссылка = &СсылкаНаДокумент";
// Делаем текст запроса универсальным под тип проводимого документа
Запрос.Текст = СтрЗаменить(Запрос.Текст, "РеализацияТоваровУслуг", Источник.Метаданные().Имя);
Запрос.УстановитьПараметр("Свойство", ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Запрет штучного товара"));
Запрос.УстановитьПараметр("СсылкаНаДокумент", Источник.Ссылка);
Отказ = НЕ Запрос.Выполнить().Пустой();
Если пользователю необходимо вывести понятное текстовое сообщение с указанием конкретного номера строки и наименования номенклатуры, вызвавшей блокировку проведения, разберем следующий алгоритм:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РеализацияТоваровУслугТовары.НомерСтроки КАК НомерСтроки,
| РеализацияТоваровУслугТовары.Номенклатура КАК Номенклатура,
| ПРЕДСТАВЛЕНИЕ(РеализацияТоваровУслугТовары.Номенклатура) КАК НоменклатураПредставление
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК НоменклатураДополнительныеРеквизиты
| ПО РеализацияТоваровУслугТовары.Номенклатура = НоменклатураДополнительныеРеквизиты.Ссылка
| И (НоменклатураДополнительныеРеквизиты.Свойство = &Свойство)
| И (НоменклатураДополнительныеРеквизиты.Значение = ИСТИНА)
|ГДЕ
| РеализацияТоваровУслугТовары.Ссылка = &СсылкаНаДокумент";
Запрос.Текст = СтрЗаменить(Запрос.Текст, "РеализацияТоваровУслуг", Источник.Метаданные().Имя);
Запрос.УстановитьПараметр("Свойство", ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Запрет штучного товара"));
Запрос.УстановитьПараметр("СсылкаНаДокумент", Источник.Ссылка);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Отказ = Истина;
ТекстСообщения = СтрШаблон("В строке №%1 обнаружена номенклатура %2 с запретом штучного товара",
Выборка.НомерСтроки,
Выборка.НоменклатураПредставление);
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения, Источник.Ссылка, "Товары", Выборка.НомерСтроки);
КонецЦикла;
При работе с дополнительными реквизитами в типовых конфигурациях (УТ, ERP, КА, БП) стоит учитывать следующие нюансы:
НайтиПоНаименованию чувствителен к изменению названия реквизита пользователями. В конфигурациях с БСП безопаснее использовать поиск по служебному имени: ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя", "ИмяСвойства") или хранить ссылку в настройках/константе.ДополнительныеРеквизиты запись попадает только тогда, когда значение было физически задано. Если флаг проверяется на ЛОЖЬ, сопоставление через ВНУТРЕННЕЕ СОЕДИНЕНИЕ не найдет отсутствующие строки. В таких ситуациях следует использовать ЛЕВОЕ СОЕДИНЕНИЕ и функцию ЕСТЬНУЛЛ().УправлениеСвойствами.ЗначениеСвойства(СсылкаНаОбъект, Свойство).