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