Как добавить отбор по местам хранения в документ «Инвентаризация товаров на складе» в 1С?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При проведении инвентаризации на крупных складах часто возникает необходимость выполнять проверку не всего склада целиком, а отдельных его зон — стеллажей, полок, ячеек или проходов. В типовых конфигурациях 1С на обычных формах (таких как «Управление торговлей 10.3» или «Управление производственным предприятием 1.3») места хранения номенклатуры носят справочный (информационный) характер. Это означает, что остатки товаров хранятся в разрезе складов, а конкретная полка или стеллаж закрепляется за карточкой товара в регистре сведений МестаХраненияНоменклатуры.

В этой статье мы подробно разберем, как доработать типовой механизм заполнения документа ИнвентаризацияТоваровНаСкладе, чтобы кладовщики могли ежедневно выбирать конкретный стеллаж и заполнять документ остатками только тех товаров, которые к нему привязаны. Мы рассмотрим два надежных способа: прямое изменение кода конфигурации и создание безопасной внешней обработки заполнения табличной части.

Почему нельзя просто нарисовать поле на форме?

Попытка вручную добавить на форму документа поле выбора места хранения и прописать его логику в процедуре «ПриИзменении» — частая ошибка начинающих разработчиков. Дело в том, что заполнение табличной части документа «Инвентаризация товаров на складе» выполняется с помощью специального платформенного объекта — ПостроительОтчета. Этот объект берет на себя всю работу по формированию сложных запросов к остаткам, расчету себестоимости по партиям и динамическому наложению фильтров.

Чтобы отбор по местам хранения заработал корректно, нам нужно внедрить логику фильтрации непосредственно в текст запроса, который использует ПостроительОтчета, а также объявить новое поле в массиве доступных отборов.

---

Способ №1. Доработка типового механизма в конфигурации

Этот способ предполагает внесение изменений в код модуля объекта документа. Прежде чем приступить, убедитесь, что ваша база данных снята с поддержки с сохранением возможности изменения.

Нам потребуется отредактировать три ключевые процедуры в модуле объекта документа ИнвентаризацияТоваровНаСкладе:

  1. ЗаполнитьНачальныеНастройки
  2. ЗаполнитьПоОстаткамНаСкладе
  3. ПерезаполнитьУчетныеКоличества

Шаг 1.1. Модернизация запроса в процедуре «ЗаполнитьНачальныеНастройки»

Найдем в модуле объекта процедуру ЗаполнитьНачальныеНастройки(ПостроительОтчета). Она отвечает за инициализацию построителя и формирование списка полей, по которым пользователь сможет делать отбор. Нам необходимо связать таблицу остатков товаров с регистром сведений МестаХраненияНоменклатуры с помощью конструкции необязательного внутреннего соединения.

Проанализируем ситуацию: фигурные скобки {} в языке запросов 1С для построителя отчета указывают на то, что соединение и условия внутри них будут применяться СУБД только тогда, когда пользователь установит соответствующий флажок отбора на форме. Если флажок снят, запрос выполнится в классическом режиме без лишних соединений, что исключает падение производительности базы данных.

Заменим текст запроса в процедуре на следующий вариант:


Процедура ЗаполнитьНачальныеНастройки(ПостроительОтчета) Экспорт
    ПостроительОтчета.Текст = "ВЫБРАТЬ
    |	ОстаткиТоваров.Номенклатура,
    |	ОстаткиТоваров.ХарактеристикаНоменклатуры," + ?(УчитыватьСерии, "
    |	ОстаткиТоваров.СерияНоменклатуры,","") + "
    |	ОстаткиТоваров.Качество,
    |	СУММА(ОстаткиТоваров.КоличествоОстаток) КАК Количество,
    |	ВЫБОР
    |		КОГДА СУММА(ОстаткиПартий.КоличествоОстаток) = 0
    |			ИЛИ СУММА(ОстаткиПартий.КоличествоОстаток) ЕСТЬ NULL
    |			ТОГДА 0
    |		ИНАЧЕ СУММА(ОстаткиПартий.СтоимостьОстаток) * СУММА(ОстаткиТоваров.КоличествоОстаток) / СУММА(ОстаткиПартий.КоличествоОстаток)
    |	КОНЕЦ КАК Сумма
    |ИЗ
    |	РегистрНакопления.ТоварыНаСкладах.Остатки(, Склад = &Склад) КАК ОстаткиТоваров
    |	ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровНаСкладах.Остатки(, Склад = &ПартионныйСклад) КАК ОстаткиПартий
    |		ПО ОстаткиТоваров.Номенклатура = ОстаткиПартий.Номенклатура
    |		И ОстаткиТоваров.ХарактеристикаНоменклатуры = ОстаткиПартий.ХарактеристикаНоменклатуры
    |		И ОстаткиТоваров.Качество = ОстаткиПартий.Качество
    |	{ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
    |		МестаХраненияНоменклатуры.Номенклатура КАК Номенклатура,
    |		СУММА(1) КАК ЧислоЯчеек
    |	ИЗ
    |		РегистрСведений.МестаХраненияНоменклатуры КАК МестаХраненияНоменклатуры
    |	ГДЕ
    |		МестаХраненияНоменклатуры.Склад = &Склад
    |		{ГДЕ
    |			МестаХраненияНоменклатуры.МестоХранения.*}
    |
    |	СГРУППИРОВАТЬ ПО
    |		МестаХраненияНоменклатуры.Номенклатура) КАК ЯчейкиНоменклатуры
    |		ПО ОстаткиТоваров.Номенклатура = ЯчейкиНоменклатуры.Номенклатура}
    |{ГДЕ
    |	ОстаткиТоваров.Номенклатура КАК Номенклатура,
    |	ОстаткиТоваров.Номенклатура.НоменклатурнаяГруппа КАК НоменклатурнаяГруппа}
    |
    |СГРУППИРОВАТЬ ПО
    |	ОстаткиТоваров.Номенклатура,
    |	ОстаткиТоваров.ХарактеристикаНоменклатуры," + ?(УчитыватьСерии, "
    |	ОстаткиТоваров.СерияНоменклатуры,", "") + "
    |	ОстаткиТоваров.Качество";

    МассивОтбора = Новый Массив;
    МассивОтбора.Добавить("Номенклатура");
    МассивОтбора.Добавить("НоменклатурнаяГруппа");
    МассивОтбора.Добавить("МестоХранения"); // Добавляем возможность отбора по ячейкам

    УправлениеОтчетами.ЗаполнитьОтбор(МассивОтбора, ПостроительОтчета);
КонецПроцедуры

Важный момент: Мы добавили строку МассивОтбора.Добавить("МестоХранения"). Благодаря этому построитель автоматически выведет поле отбора на форму во вкладке настроек условий проведения инвентаризации.

Шаг 1.2. Изменение логики в процедуре «ЗаполнитьПоОстаткамНаСкладе»

Эта процедура отвечает за непосредственное заполнение табличной части документа физическими остатками. Нам нужно внедрить разработанный подзапрос в обе ветки алгоритма (для розничных складов НТТ и для оптовых складов). Найдем процедуру ЗаполнитьПоОстаткамНаСкладе(ПостроительОтчета, ТолькоУчетные = Ложь) и внесем изменения в тексты запросов.

Для розницы (блок Если Склад.ВидСклада = Перечисления.ВидыСкладов.НТТ Тогда) добавим соединение:


|	{ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
|		МестаХраненияНоменклатуры.Номенклатура КАК Номенклатура,
|		СУММА(1) КАК ЧислоЯчеек
|	ИЗ
|		РегистрСведений.МестаХраненияНоменклатуры КАК МестаХраненияНоменклатуры
|	ГДЕ
|		МестаХраненияНоменклатуры.Склад = &Склад
|		{ГДЕ
|			МестаХраненияНоменклатуры.МестоХранения.*}
|
|	СГРУППИРОВАТЬ ПО
|		МестаХраненияНоменклатуры.Номенклатура) КАК ЯчейкиНоменклатуры
|		ПО ОстаткиТоваров.Номенклатура = ЯчейкиНоменклатуры.Номенклатура}

Аналогичное соединение необходимо вставить в секцию Иначе для оптовых и обычных розничных складов. Полный текст измененной процедуры вы можете увидеть в сообщении №28 обсуждения на форуме.

Шаг 1.3. Обновление процедуры «ПерезаполнитьУчетныеКоличества»

Функция перезаполнения учетных данных вызывается, когда инвентаризационная опись уже создана, но в процессе работы на складе изменились остатки, и их нужно актуализировать. Чтобы при этом из документа не исчезли товары, отфильтрованные по ячейкам, или наоборот, не добавился лишний ассортимент с других стеллажей, обязательно обновите запрос и в процедуре ПерезаполнитьУчетныеКоличества(ПостроительОтчета).

Внедрите блок {ВНУТРЕННЕЕ СОЕДИНЕНИЕ...} во все запросы этой процедуры перед секцией {ГДЕ ...} по аналогии с предыдущим шагом.

---

Способ №2. Использование внешней обработки заполнения табличной части

Если вы не имеете опыта программирования в среде 1С или ваша конфигурация находится на строгой поддержке (обновляется в автоматическом режиме), прямое вмешательство в код крайне нежелательно. Любая ошибка в синтаксисе запроса может парализовать проведение инвентаризаций на предприятии.

В этом случае отличной альтернативой станет создание **внешней обработки заполнения табличной части**.

Рассмотрим по шагам, как устроен этот механизм:

  1. Создается внешний файл обработки с расширением .epf.
  2. В модуле обработки описывается экспортная функция Инициализировать, принимающая в качестве параметра объект документа ИнвентаризацияТоваровНаСкладе.
  3. При вызове обработки открывается удобная диалоговая форма, где кладовщик выбирает нужное место хранения (стеллаж/полку) из справочника МестаХранения.
  4. По нажатию кнопки «Заполнить» обработка выполняет запрос к остаткам товаров на выбранном складе, соединяя их с регистром МестаХраненияНоменклатуры по указанному стеллажу, и очистив табличную часть документа, переносит туда отфильтрованные строки.

Преимущества использования внешней обработки:

---

Полезные советы и тонкости настройки интерфейса

Если вы все же выбрали Способ №1 и доработали запросы внутри конфигурации, вам потребуется вывести управление отбором для пользователей. В типовом решении УТ 10.3/УПП 1.3 на форме документа уже присутствует табличное поле отборов построителя отчета. Новое поле «Место хранения» появится там автоматически.

Если в вашей нетиповой (доработанной) форме отборы выведены в виде отдельных полей ввода, свяжите их напрямую со свойствами построителя отчета через палитру свойств элементов управления на форме:

Важное предупреждение: Перед настройкой элементов формы обязательно убедитесь, что выполнена процедура инициализации поля в модуле объекта (см. Шаг 1.1), иначе при открытии документа система выдаст критическую ошибку «Поле объекта не обнаружено (МестоХранения)» и закроет программу.

← На главную