Как в 1С:УНФ 1.6 добавить колонку «Свободный остаток» в форму списка Номенклатуры?

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

При работе в программе «1С:Управление нашей фирмой» (УНФ) версии 1.6 менеджеры по продажам часто сталкиваются с необходимостью видеть реальный свободный остаток товара непосредственно в списке номенклатуры. Стандартный общий остаток не всегда информативен, так как часть товара может находиться в жестком резерве под конкретные заказы покупателей.

В этой статье мы подробно разберем, как решить эту задачу. Мы выясним, где и как хранятся резервы в УНФ 1.6, проанализируем типичные ошибки разработчиков при составлении запросов для динамических списков, напишем правильный и оптимизированный запрос, а также разберем, почему добавленная колонка может не отображаться на форме и как это исправить.

Понимание архитектуры учета запасов и резервов в УНФ 1.6

Прежде чем переходить к написанию кода и изменению запросов, давайте разберем, как именно система хранит информацию об остатках и резервах. В отличие от более крупных конфигураций (таких как «1С:ERP» или «1С:Управление торговлей»), в УНФ 1.6 нет отдельного специализированного регистра для свободных остатков.

Все данные о складских запасах и резервах сосредоточены в одном регистре накопления — РегистрНакопления.Запасы. Этот регистр имеет два ключевых измерения, которые определяют логику резервирования:

  1. Номенклатура (и при наличии характеристика, партия, склад).
  2. ЗаказПокупателя. Это измерение является ключевым для нашей задачи.

Логика разделения остатков выглядит следующим образом:

Таким образом, формула расчета выглядит крайне просто: свободный остаток — это остаток по регистру Запасы с установленным фильтром по пустой ссылке заказа покупателя.

Разбор критических ошибок из практики разработчиков

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


ВЫБРАТЬ
    СправочникНоменклатура.Ссылка КАК Ссылка,
    ...
    ЕСТЬNULL(Запасы.Количество, 0) КАК СвободныйОстаток
ИЗ
    РегистрНакопления.Запасы КАК Запасы
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СправочникНоменклатура
        ПО Запасы.Номенклатура = СправочникНоменклатура.Ссылка
ГДЕ
    Запасы.Количество = ЗНАЧЕНИЕ(Документ.ЗаказПокупателя.ПустаяСсылка)

Давайте выясним причины, по которым этот запрос не будет работать или приведет к критическому падению производительности системы:

  1. Использование физической таблицы вместо виртуальной. В запросе используется таблица РегистрНакопления.Запасы. Это физическая таблица движений, которая хранит всю историю приходов и расходов за все время ведения учета. Обращение к ней в динамическом списке приведет к тому, что система начнет сканировать миллионы строк движений при каждом открытии списка номенклатуры. Для получения текущих остатков необходимо использовать исключительно виртуальную таблицу РегистрНакопления.Запасы.Остатки.
  2. Ошибочное левое соединение (LEFT JOIN). В некорректном примере соединение идет от таблицы регистра к справочнику номенклатуры. При такой структуре соединения из списка номенклатуры полностью исчезнут все товары, по которым никогда не было движений (новые товары или позиции без остатков). Соединение всегда должно идти от справочника Номенклатура к виртуальной таблице остатков регистра.
  3. Синтаксическая ошибка сопоставления типов. Конструкция Запасы.Количество = ЗНАЧЕНИЕ(Документ.ЗаказПокупателя.ПустаяСсылка) пытается сравнить числовое поле количества с ссылкой на документ. Это вызовет синтаксическую ошибку СУБД и аварийное завершение работы формы. Сравнивать с пустой ссылкой нужно измерение ЗаказПокупателя.

Пишем правильный и оптимизированный запрос для динамического списка

Для того чтобы динамический список работал быстро и без сбоев даже на больших базах данных, мы должны использовать виртуальную таблицу остатков и наложить фильтр по пустому заказу непосредственно в параметрах этой виртуальной таблицы. Это позволит СУБД отсечь ненужные данные на самом раннем этапе выполнения запроса.

Рассмотрим правильный вариант SQL-подобного запроса для динамического списка формы номенклатуры:


ВЫБРАТЬ
	СправочникНоменклатура.Ссылка КАК Ссылка,
	СправочникНоменклатура.Код КАК Код,
	СправочникНоменклатура.Наименование КАК Наименование,
	СправочникНоменклатура.Артикул КАК Артикул,
	СправочникНоменклатура.ЭтоГруппа КАК ЭтоГруппа,
	СправочникНоменклатура.Недействителен КАК Недействителен,
	ЕСТЬNULL(ЗапасыОстатки.КоличествоОстаток, 0) КАК СвободныйОстаток
ИЗ
	Справочник.Номенклатура КАК СправочникНоменклатура
	ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Запасы.Остатки(, ЗаказПокупателя = ЗНАЧЕНИЕ(Документ.ЗаказПокупателя.ПустаяСсылка)) КАК ЗапасыОстатки
		ПО СправочникНоменклатура.Ссылка = ЗапасыОстатки.Номенклатура

Проанализируем ключевые моменты этого запроса:

Решение проблемы с отображением колонки на форме

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

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

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

Рассмотрим пример кода, который необходимо встроить в конец процедуры ПриСозданииНаСервере или вызвать в рамках расширения конфигурации:


&НаСервере
Процедура ДобавитьСвободныйОстатокВЗапросСписка()
    
    // Получаем текущий текст запроса динамического списка
    ТекстЗапроса = Список.ТекстЗапроса;
    
    // Проверим, не добавлен ли уже свободный остаток программно
    Если Найти(ТекстЗапроса, "СвободныйОстаток") = 0 Тогда
        
        // Подготавливаем фрагмент для левого соединения
        СтрокаСоединения = 
        "ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Запасы.Остатки(, ЗаказПокупателя = ЗНАЧЕНИЕ(Документ.ЗаказПокупателя.ПустаяСсылка)) КАК ЗапасыОстатки
        ПО СправочникНоменклатура.Ссылка = ЗапасыОстатки.Номенклатура";
        
        // Внедряем выбор поля свободного остатка
        ТекстЗапроса = СтрЗаменить(ТекстЗапроса, 
            "СправочникНоменклатура.Ссылка КАК Ссылка,", 
            "СправочникНоменклатура.Ссылка КАК Ссылка, ЕСТЬNULL(ЗапасыОстатки.КоличествоОстаток, 0) КАК СвободныйОстаток,");
            
        // Внедряем само левое соединение перед условиями или в конец связей
        ТекстЗапроса = СтрЗаменить(ТекстЗапроса, 
            "ИЗ Справочник.Номенклатура КАК СправочникНоменклатура", 
            "ИЗ Справочник.Номенклатура КАК СправочникНоменклатура " + СтрокаСоединения);
            
        // Возвращаем измененный текст обратно в динамический список
        Список.ТекстЗапроса = ТекстЗапроса;
        
    КонецЕсли;

КонецПроцедуры

Использование программного изменения запроса гарантирует, что ваши доработки динамического списка не пропадут при обновлении конфигурации или при изменении настроек отображения интерфейса самой системой.

Настройка пользовательской видимости колонки

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

Чтобы сбросить настройки или принудительно вывести колонку, выполните следующие шаги в режиме «1С:Предприятие»:

  1. Откройте форму списка справочника Номенклатура.
  2. В правом верхнем углу нажмите кнопку Еще и выберите пункт меню Изменить форму....
  3. В открывшемся дереве элементов найдите элемент динамического списка (обычно называется Список) и найдите в нем поле СвободныйОстаток.
  4. Убедитесь, что напротив этого поля установлена галочка активности.
  5. Если поля нет в списке или настройки сбились, нажмите кнопку Еще (внутри окна настройки формы) и выберите пункт Установить стандартные настройки. Это сбросит кэш и принудительно применит структуру формы, заданную нами в конфигураторе.

Альтернативное решение: использование расширений конфигурации (cfe)

Если ваша база УНФ находится на поддержке и вы не хотите снимать ее с автоматического обновления, наиболее правильным архитектурным решением будет использование Расширения конфигурации.

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

← На главную