Как настроить отбор складов по организации и управлять временем документов в 1С:УНФ

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

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

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

Часть 1. Архитектура складов и организаций в 1С:УНФ

Прежде чем приступать к написанию кода, проанализируем структуру метаданных конфигурации 1С:УНФ. В отличие от тяжелых ERP-систем, где склады могут иметь жесткую подчиненность организациям на уровне владельцев справочников, в УНФ используется справочник СтруктурныеЕдиницы. Этот справочник является универсальным: в нем хранятся как оптовые склады, так и розничные магазины, а также производственные подразделения компании.

Этот справочник не имеет стандартного иерархического владельца «Организации». Однако разработчики фирмы «1С» предусмотрели в нем реквизит Организация с типом ссылки на справочник Организации. Это дает нам полную техническую возможность связать склад с конкретным юридическим лицом. Если этот реквизит заполнен в карточке склада, мы можем использовать его для фильтрации в документах.

Часть 2. Настройка динамического отбора складов через СвязиПараметровВыбора

Самый правильный и соответствующий стандартам разработки «1С» способ ограничить выбор складов — использовать механизм **связей параметров выбора** (СвязиПараметровВыбора). Этот механизм заставляет платформу автоматически отслеживать изменение реквизита Организация на форме документа и мгновенно применять фильтр к списку выбора складов.

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

Рассмотрим по шагам программную реализацию этого метода в расширении для формы документа (например, «Заказ покупателя» или «Приходная накладная»):


&После("ПриСозданииНаСервере")
Процедура ИН_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
    
    // Создаем новый массив для хранения связей параметров выбора
    НовыеСвязи = Новый Массив;
    
    // Переносим существующие связи, чтобы не сломать типовой функционал
    Для Каждого Связь Из Элементы.СтруктурнаяЕдиница.СвязиПараметровВыбора Цикл
        НовыеСвязи.Добавить(Связь);
    КонецЦикла;
    
    // Добавляем новую связь: фильтруем склады по организации, указанной в документе
    // Первый параметр — путь к реквизиту-фильтру в справочнике ("Отбор.Организация")
    // Второй параметр — путь к реквизиту формы, откуда берется значение ("Объект.Организация")
    НовыеСвязи.Добавить(Новый СвязьПараметраВыбора("Отбор.Организация", "Объект.Организация"));
    
    // Перезаписываем связи параметров выбора элемента формы
    Элементы.СтруктурнаяЕдиница.СвязиПараметровВыбора = Новый ФиксированныйМассив(НовыеСвязи);
    
КонецПроцедуры

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

Этот метод прекрасен тем, что работает полностью на стороне платформы. Как только пользователь меняет организацию в шапке документа, платформа сама отправляет запрос к базе данных и обновляет список доступных для выбора складов, оставляя только те, у которых реквизит Организация совпадает с выбранной.

Часть 3. Альтернативный метод: жесткая фильтрация конкретных складов

Рассмотрим более сложную ситуацию. Предположим, у нас есть организация «ООО ХХХ (Плюс)», для которой нужно жестко закрепить один конкретный склад (например, «Склад ХХХ (Плюс)»), а для других организаций оставить стандартное поведение или реализовать иную сложную логику. В этом случае стандартные связи параметров выбора могут не справиться, и нам потребуется использовать программную установку ПараметрыВыбора на клиенте в момент начала выбора.

Разберем пример кода, который перехватывает событие начала выбора склада на форме документа:


&НаКлиенте
Процедура ИН_СтруктурнаяЕдиницаНачалоВыбораПеред(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    // Проверяем заполненность организации и ее наименование
    Если ЗначениеЗаполнено(Объект.Организация) И Объект.Организация.Наименование = "ООО ""ХХХ"" (ПЛЮС)" Тогда
        
        // Отменяем стандартную обработку выбора, чтобы задать свои параметры
        СтандартнаяОбработка = Ложь;
        
        // Массив для хранения разрешенных складов
        МассивРазрешенныхСкладов = Новый Массив;
        
        // Получаем ссылку на конкретный склад (в реальной базе лучше использовать предопределенные элементы или настройки)
        СкладСсылка = ПолучитьСкладПоНаименованию("Склад ХХХ (Плюс)");
        Если ЗначениеЗаполнено(СкладСсылка) Тогда
            МассивРазрешенныхСкладов.Добавить(СкладСсылка);
        КонецЕсли;
        
        // Формируем параметры отбора по ссылке
        ПараметрыОтбора = Новый Структура;
        ПараметрыОтбора.Вставить("Ссылка", Новый ФиксированныйМассив(МассивРазрешенныхСкладов));
        
        // Формируем параметры открытия формы выбора
        ПараметрыФормы = Новый Структура;
        ПараметрыФормы.Вставить("Отбор", ПараметрыОтбора);
        
        // Открываем форму выбора справочника с нашими параметрами отбора
        ОткрытьФорму("Справочник.СтруктурныеЕдиницы.ФормаВыбора", ПараметрыФормы, Элемент);
        
    КонецЕсли;
    
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьСкладПоНаименованию(ИмяСклада)
    Возврат Справочники.СтруктурныеЕдиницы.НайтиПоНаименованию(ИмяСклада);
КонецФункции

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

Часть 4. Управление временем документов для предотвращения отрицательных остатков

Вторая проблема, часто возникающая при параллельной работе нескольких складов — хронологическая последовательность проведения документов. Типичный пример: документ «Сборка запасов» проводится в течение дня. Если комплектующие поступили на склад в 12:00, а сборка готовой продукции была проведена «задним числом» или просто в 09:00 утра того же дня, система выдаст ошибку о нехватке запасов, так как на момент сборки комплектующих еще не было физически.

Чтобы решить эту проблему, разработчики часто пытаются принудительно установить время проведения таких документов на начало дня (00:00:00) или сделать документ «первым» в пределах суток.

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

Правильный способ управления датой и временем нового документа — использование предопределенного события формы **ПередЗаписьюНаСервере** или подписки на событие **ПередЗаписью** в модуле самого объекта. Разберем правильный вариант реализации на уровне формы документа в расширении:


&НаСервере
Процедура ИН_ПередЗаписьюНаСервереПеред(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    
    // Корректируем время только для новых, еще не записанных в базу данных документов
    Если ТекущийОбъект.ЭтоНовый() Тогда
        
        // Вариант А: Установка времени документа строго на начало дня (00:00:00)
        ТекущийОбъект.Дата = НачалоДня(ТекущийОбъект.Дата);
        
        // Вариант Б: Использование стандартного механизма платформы для позиционирования документа первым в дне
        // Этот метод автоматически сдвигает документ в самую раннюю позицию в пределах указанной даты
        ТекущийОбъект.УстановитьВремя(РежимАвтоВремя.Первым);
        
    КонецЕсли;
    
КонецПроцедуры

В данном коде параметр ТекущийОбъект имеет тип ДокументОбъект.СборкаЗапасов. Любые изменения, внесенные в его свойства в процедуре ПередЗаписьюНаСервере, будут гарантированно и корректно записаны в базу данных платформой «1С:Предприятие» без необходимости дополнительных преобразований типов.

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

Резюме

Мы успешно решили две важные задачи автоматизации складского учета в 1С:УНФ с помощью механизмов расширений:

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

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

← На главную