В процессе эксплуатации 1С:ERP часто возникает ситуация, когда необходимо разграничить «старую» и «новую» номенклатуру. Например, при переходе на новые справочники по ГОСТу, когда старые позиции остаются в базе только для учета остатков, а в новые документы (Заказы клиентов, Заказы поставщикам) должны попадать только новые элементы. Основная сложность заключается в том, чтобы реализовать проверку вхождения номенклатуры в разрешенный список, не снимая основную конфигурацию с поддержки. Рассмотрим подробнее, где и как можно хранить этот набор элементов и как реализовать логику проверки.
Это самый «чистый» способ с точки зрения методологии 1С. Хотя на первый взгляд может показаться, что у справочника ВидыНоменклатуры нет дополнительных реквизитов, в 1С:ERP предусмотрен механизм дополнительных сведений, который не требует изменения структуры таблиц базы данных.
Разберем по шагам, как это настроить:
Виды номенклатуры и добавим новое свойство, например, «Актуален для заказов» с типом Булево.Проанализируем программную часть реализации в расширении. Для проверки нам потребуется обращение к регистру сведений ДополнительныеСведения. Посмотрим на пример кода, который можно разместить в модуле объекта документа в процедуре ПередЗаписью:
&После("ПередЗаписью")
Процедура Расш1_ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Для Каждого СтрокаТЧ Из Товары Цикл
ВидНом = СтрокаТЧ.Номенклатура.ВидНоменклатуры;
// Получаем значение доп. сведения
ЗначениеСвойства = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ВидНом, "ДополнительныеСведения");
// Либо через запрос к РС.ДополнительныеСведения
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДополнительныеСведения.Значение КАК ЭтоНовыйВид
|ИЗ
| РегистрСведения.ДополнительныеСведения КАК ДополнительныеСведения
|ГДЕ
| ДополнительныеСведения.Объект = &Объект
| И ДополнительныеСведения.Свойство = &Свойство";
Запрос.УстановитьПараметр("Объект", ВидНом);
Запрос.УстановитьПараметр("Свойство", ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Актуален для заказов"));
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Если Не Выборка.ЭтоНовыйВид Тогда
ТекстОшибки = СтрШаблон("Номенклатура %1 относится к устаревшему виду!", СтрокаТЧ.Номенклатура);
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстОшибки, , "Товары[" + (Товары.Индекс(СтрокаТЧ)) + "].Номенклатура");
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Выясним причину, по которой этот метод считается наиболее производительным в 1С:ERP. Система сегментации специально создана для группировки номенклатуры по произвольным правилам. Мы можем создать сегмент «Разрешенные к продаже».
Преимущество этого подхода в том, что проверка вхождения в сегмент работает крайне быстро, так как данные хранятся в отдельном регистре сведений НоменклатураСегмента. Мы можем настроить формирование сегмента динамически (по фильтру вида номенклатуры) или вручную.
Рассмотрим код проверки вхождения в сегмент:
// В расширении проверяем вхождение в сегмент
ПараметрыОтбора = Новый Структура("Номенклатура", ТекущаяНоменклатура);
Если Не СегментыВызовСервера.ПринадлежитНоменклатураСегменту(ТекущаяНоменклатура, СсылкаНаСегмент) Тогда
// Запрет проведения
КонецЕсли;
Если задача стоит не только в программном запрете, но и в том, чтобы пользователи сами видели разницу при выборе, можно прибегнуть к простому, но эффективному способу — префиксации наименований видов номенклатуры. Например, добавить в начало старых видов строку «(СТАРЫЙ) ».
Проанализируем ситуацию: это решение не требует создания новых объектов метаданных. Проверка в коде расширения будет выглядеть следующим образом:
&Перед("ПередЗаписью")
Процедура Расш1_ПроверитьВидНоменклатуры(Отказ, РежимЗаписи, РежимПроведения)
Для Каждого Стр Из Товары Цикл
НаименованиеВида = Стр.Номенклатура.ВидНоменклатуры.Наименование;
Если Лев(ВРег(НаименованиеВида), 8) = "(СТАРЫЙ)" Тогда
Сообщить("Выбор номенклатуры из архивных видов запрещен!");
Отказ = Истина;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Важный момент: если наименование вида номенклатуры используется в печатных формах, этот метод может не подойти. Однако в большинстве типовых шаблонов 1С:ERP выводится наименование самой номенклатуры, а не её вида.
Если набор «новых» видов номенклатуры жестко зафиксирован и меняется крайне редко (например, при обновлении системы), мы можем хранить их уникальные идентификаторы (GUID) в текстовом макете прямо внутри расширения.
Разберем этот алгоритм:
Текстовый документ.Посмотрим на пример функции получения списка:
Функция ПолучитьСписокРазрешенныхВидов()
СписокВидов = Новый Массив;
Макет = УправлениеНебольшойФирмойПереопределяемый.ПолучитьМакет("Расш1_СписокВидов");
Для НомерСтроки = 1 По Макет.КоличествоСтрок() Цикл
ТекстGUID = Макет.ПолучитьСтроку(НомерСтроки);
СписокВидов.Добавить(Справочники.ВидыНоменклатуры.ПолучитьСсылку(Новый УникальныйИдентификатор(ТекстGUID)));
КонецЦикла;
Возврат СписокВидов;
КонецФункции
Существует «хакерский» способ хранения настроек без создания своих регистров. В системе часто присутствует регистр сведений СоответствияОбъектовИнформационныхБаз. Его можно использовать как универсальное хранилище «Ключ — Значение».
В качестве Узла информационной базы можно выбрать пустую ссылку, в Собственный объект записать ссылку на вид номенклатуры, а в текстовые поля — пометку о его статусе. Это позволяет избежать изменения структуры конфигурации, используя уже имеющуюся таблицу.
Выбор конкретного метода зависит от ваших приоритетов:
В любом случае, использование расширений для реализации логики проверки (ПередЗаписью или ОбработкаПроверкиЗаполнения) позволит вам сохранить конфигурацию на поддержке и обеспечит легкость будущих обновлений 1С:ERP.