При программном создании документов в системах 1С, особенно в комплексных конфигурациях вроде 1С:Управление тортовлей (УТ) 11.4, мы часто сталкиваемся с необходимостью тщательного заполнения множества реквизитов. Одной из распространенных проблем, с которой мы можем столкнуться при создании документа "Реализация товаров и услуг", является ошибка "Не заполнена аналитика учета номенклатуры". Давайте вместе разберем, почему возникает эта ошибка и как ее эффективно исправить, используя инструмент для исправления ключей аналитики учета и видов запасов, обеспечив корректное проведение документов.
Эта ошибка, как правило, указывает на то, что один из ключевых аналитических разрезов для учета запасов не был заполнен. В частности, в конфигурациях 1С:УТ 11.4 и более новых версиях, таким обязательным реквизитом часто является ВидЗапасов. В новых версиях также важно корректное заполнение регистра "Запасы и потребности".
Прежде всего, давайте проанализируем, почему система требует заполнения ВидаЗапасов. В 1С:Управление торговлей реализован достаточно сложный механизм учета запасов, который позволяет разделять товары по различным категориям, например, "Собственный товар", "Принятый на комиссию товар", "Переданный на комиссию товар" и так далее. Это разделение критически важно для корректного формирования финансовых и управленческих отчетов, а также для правильного расчета себестоимости. Если при движении товара (например, при реализации) не указан его вид запасов, система не может однозначно определить, к какой категории относится этот товар и как его следует списать, что приводит к указанной ошибке.
Для каждого элемента номенклатуры на конкретном складе и в рамках определенной организации система хранит информацию о виде запасов в регистре сведений ВидыЗапасовНоменклатуры. Поэтому наша задача при программном создании документа заключается в том, чтобы либо найти существующий вид запасов для комбинации номенклатуры, склада и организации, либо создать его, если он отсутствует, а затем правильно присвоить его соответствующей строке табличной части документа.
Начнем с базовой структуры программного создания документа. Мы создаем новый документ типа "Реализация товаров и услуг" и заполняем его основные реквизиты, такие как Дата, Организация, Контрагент, ДоговорКонтрагента, Склад, Валюта и Подразделение. Эти шаги являются стандартными для любого программного создания документа.
НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Организация = Справочники.Организации.НайтиПоНаименованию("Наша Организация");
НовыйДокумент.Контрагент = Справочники.Контрагенты.НайтиПоНаименованию("Покупатель");
НовыйДокумент.ДоговорКонтрагента = НовыйДокумент.Контрагент.Договор; // Пример: получаем договор по умолчанию
НовыйДокумент.Склад = Справочники.Склады.НайтиПоНаименованию("Основной склад");
НовыйДокумент.Валюта = Справочники.Валюты.НайтиПоКоду("643");
НовыйДокумент.Подразделение = Справочники.ПодразделенияОрганизаций.НайтиПоНаименованию("Отдел продаж");
Далее мы приступаем к заполнению табличной части "Товары". Для каждой строки мы указываем Номенклатуру, Количество, Цену, Сумму. Обратите внимание, что реквизит ЕдиницаИзмерения также должен быть заполнен корректно. Лучше всего брать его из самого элемента номенклатуры или из единицы хранения, если она задана.
НоваяСтрока = НовыйДокумент.Товары.Добавить();
НоваяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию("Товар 1");
НоваяСтрока.Количество = 10;
НоваяСтрока.Цена = 100;
НоваяСтрока.Сумма = НоваяСтрока.Количество * НоваяСтрока.Цена;
// Корректное заполнение единицы измерения
Если НоваяСтрока.Номенклатура <> Неопределено Тогда
НоваяСтрока.ЕдиницаИзмерения = НоваяСтрока.Номенклатура.ЕдиницаХранения;
КонецЕсли;
Это самый важный шаг для решения нашей проблемы. Мы должны определить и присвоить ВидЗапасов каждой строке табличной части "Товары". В некоторых случаях может помочь автоматическое исправление видов запасов в документах на основе данных регистров остатков. Для этого мы можем создать вспомогательную функцию, которая будет искать или создавать необходимый вид запасов. Рассмотрим подробнее, как мы можем реализовать такую функцию.
Мы предлагаем несколько подходов для получения ВидаЗапасов:
Основной источник информации о видах запасов — это регистр сведений ВидыЗапасовНоменклатуры. Мы можем выполнить запрос к этому регистру, чтобы найти запись, соответствующую нашей номенклатуре, складу и организации.
// Вспомогательная функция для получения или создания вида запасов
Функция ПолучитьВидЗапасовДляНоменклатуры(Номенклатура, Склад, Организация) Экспорт
// Сначала ищем существующий вид запасов в регистре
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ВидыЗапасовНоменклатуры.ВидЗапасов КАК ВидЗапасов
|ИЗ
| РегистрСведений.ВидыЗапасовНоменклатуры КАК ВидыЗапасовНоменклатуры
|ГДЕ
| ВидыЗапасовНоменклатуры.Номенклатура = &Номенклатура
| И ВидыЗапасовНоменклатуры.Склад = &Склад
| И ВидыЗапасовНоменклатуры.Организация = &Организация";
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Запрос.УстановитьПараметр("Склад", Склад);
Запрос.УстановитьПараметр("Организация", Организация);
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
Возврат Выборка.ВидЗапасов;
КонецЕсли;
Возврат Неопределено; // Если ничего не нашли
КонецФункции;
После реализации этой функции, мы можем использовать ее в основном коде для заполнения ВидаЗапасов:
// В основном коде, после заполнения Номенклатуры
ЗначениеВидаЗапасов = ПолучитьВидЗапасовДляНоменклатуры(НоваяСтрока.Номенклатура, НовыйДокумент.Склад, НовыйДокумент.Организация);
Если ЗначениеВидаЗапасов <> Неопределено Тогда
НоваяСтрока.ВидЗапасов = ЗначениеВидаЗапасов;
Иначе
Сообщить("Внимание: Не найден вид запасов для номенклатуры " + НоваяСтрока.Номенклатура + ". Возможно, потребуется создать или использовать стандартный.");
КонецЕсли;
Часто в системе уже существует стандартный вид запасов, например, "Собственный товар". Если мы не смогли найти специфичный вид запасов через регистр сведений, мы можем попытаться использовать этот стандартный вариант. Если же и его нет, или он нам не подходит, мы можем программно создать новый элемент справочника ВидыЗапасов.
Модифицируем нашу функцию ПолучитьВидЗапасовДляНоменклатуры, чтобы она включала логику поиска стандартного вида запасов и его создания при необходимости:
// Универсальная функция для получения или создания вида запасов
Функция ПолучитьИлиСоздатьВидЗапасов(Номенклатура, Склад, Организация) Экспорт
// 1. Сначала ищем существующий вид запасов в регистре ВидыЗапасовНоменклатуры
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ВидыЗапасовНоменклатуры.ВидЗапасов КАК ВидЗапасов
|ИЗ
| РегистрСведений.ВидыЗапасовНоменклатуры КАК ВидыЗапасовНоменклатуры
|ГДЕ
| ВидыЗапасовНоменклатуры.Номенклатура = &Номенклатура
| И ВидыЗапасовНоменклатуры.Склад = &Склад
| И ВидыЗапасовНоменклатуры.Организация = &Организация";
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Запрос.УстановитьПараметр("Склад", Склад);
Запрос.УстановитьПараметр("Организация", Организация);
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
Возврат Выборка.ВидЗапасов;
КонецЕсли;
// 2. Если не нашли, попробуем найти стандартный "Собственный товар"
СтандартныйВидЗапасов = Справочники.ВидыЗапасов.НайтиПоНаименованию("Собственный товар");
Если СтандартныйВидЗапасов <> Неопределено Тогда
// Найден стандартный вид запасов, теперь его нужно связать
// Создадим новую запись в регистре ВидыЗапасовНоменклатуры для данной комбинации
// Это обеспечит, что в следующий раз он будет найден по запросу
НоваяЗаписьРегистра = РегистрыСведений.ВидыЗапасовНоменклатуры.СоздатьМенеджерЗаписи();
НоваяЗаписьРегистра.Номенклатура = Номенклатура;
НоваяЗаписьРегистра.Склад = Склад;
НоваяЗаписьРегистра.Организация = Организация;
НоваяЗаписьРегистра.ВидЗапасов = СтандартныйВидЗапасов;
Попытка
НоваяЗаписьРегистра.Записать(Истина); // Записываем с замещением
Исключение Как Искл
Сообщить("Не удалось записать новый вид запасов в регистр: " + Искл.Описание);
КонецПопытки;
Возврат СтандартныйВидЗапасов;
КонецЕсли;
// 3. Если стандартный вид запасов не найден, создаем новый
НовыйВидЗапасов = Справочники.ВидыЗапасов.СоздатьЭлемент();
НовыйВидЗапасов.Наименование = "Автоматически созданный вид запасов " + Формат(ТекущаяДата(), "ДФ=дд.ММ.гггг ЧЧ:мм:сс");
Попытка
НовыйВидЗапасов.Записать();
// После создания элемента справочника, также связываем его с номенклатурой, складом, организацией
НоваяЗаписьРегистра = РегистрыСведений.ВидыЗапасовНоменклатуры.СоздатьМенеджерЗаписи();
НоваяЗаписьРегистра.Номенклатура = Номенклатура;
НоваяЗаписьРегистра.Склад = Склад;
НоваяЗаписьРегистра.Организация = Организация;
НоваяЗаписьРегистра.ВидЗапасов = НовыйВидЗапасов;
Попытка
НоваяЗаписьРегистра.Записать(Истина);
Исключение Как Искл
Сообщить("Не удалось записать новый автоматически созданный вид запасов в регистр: " + Искл.Описание);
КонецПопытки;
Возврат НовыйВидЗапасов;
Исключение Как Искл
Сообщить("Не удалось создать новый элемент справочника ВидыЗапасов: " + Искл.Описание);
Возврат Неопределено;
КонецПопытки;
КонецФункции;
Теперь мы можем применить эту доработанную функцию в нашем основном коде:
// В цикле по товарам или для вашей одной строки
НоваяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию("Товар 1");
НоваяСтрока.Количество = 10;
НоваяСтрока.Цена = 100;
НоваяСтрока.Сумма = НоваяСтрока.Количество * НоваяСтрока.Цена;
Если НоваяСтрока.Номенклатура <> Неопределено Тогда
НоваяСтрока.ЕдиницаИзмерения = НоваяСтрока.Номенклатура.ЕдиницаХранения;
КонецЕсли;
// Получаем или создаем вид запасов
НоваяСтрока.ВидЗапасов = ПолучитьИлиСоздатьВидЗапасов(НоваяСтрока.Номенклатура, НовыйДокумент.Склад, НовыйДокумент.Организация);
Если НовыйДокумент.Товары.Количество() > 0 Тогда
// Заполняем другие обязательные реквизиты, например, статью расходов, если это требуется
// В УТ 11.4 часто требуется указание статьи затрат для некоторых операций
Если НовыйДокумент.Товары[0].ВидЗапасов <> Неопределено Тогда
// Пример: заполнение статьи доходов/расходов, если необходимо
// НовыйДокумент.Товары[0].СтатьяДоходовРасходов = Справочники.СтатьиДоходовРасходов.НайтиПоНаименованию("Себестоимость проданных товаров");
КонецЕсли;
КонецЕсли;
После того как все необходимые реквизиты, включая ВидЗапасов, заполнены, мы можем попытаться записать и провести документ.
Попытка
// Перед записью рекомендуется выполнить проверку заполнения или заполнение по умолчанию
НовыйДокумент.ЗаполнитьЦеныПоВидуЦен(Справочники.ВидыЦен.НайтиПоНаименованию("Цена продажи")); // Пример
НовыйДокумент.ЗаполнитьОснованиеПриОтгрузке(); // Например, для автоматического заполнения
НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);
Сообщить("Документ Реализация товаров и услуг " + НовыйДокумент.Номер + " от " + НовыйДокумент.Дата + " успешно создан и проведен!");
Исключение Как Искл
Сообщить("Ошибка при записи или проведении документа: " + Искл.Описание);
КонецПопытки;
НайтиПоНаименованию) могут снизить производительность. Для оптимизации используйте кэширование справочников или запросы с пакетированием.ВидыЗапасовНоменклатуры: Помните, что записи в этом регистре создаются автоматически при первом движении номенклатуры с определенным видом запасов на складе организации. Наша функция лишь имитирует этот процесс или находит уже созданную запись.Решая проблему с ошибкой "Не заполнена аналитика учета номенклатуры" путем корректного программного заполнения ВидаЗапасов, мы обеспечиваем надежную работу нашего решения по автоматическому созданию документов в 1С:УТ 11.4. Всегда помните о специфике конфигурации и старайтесь максимально точно воспроизводить логику работы типовых механизмов системы.