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