Как проверить существование документа и открыть его форму при старте системы 1С

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

При разработке интерфейсов для кассиров или операторов часто возникает задача: при запуске программы автоматически проверять, создан ли уже сегодня определенный документ (например, ТабельСмены или ОтчетОРозничныхПродажах). Если документ есть, его нужно открыть; если нет — создать новый или предложить регистрацию. Типичная ошибка начинающих разработчиков — попытка вызвать процедуру, находящуюся внутри модуля формы документа, напрямую из глобального модуля. Разберем, почему это не работает и как реализовать задачу правильно, используя архитектуру платформы 1С.

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

Разберем фундаментальное ограничение: модуль формы существует только тогда, когда создана сама форма (окно в интерфейсе). Когда система выполняет процедуру ПриНачалеРаботыСистемы в глобальном модуле, ни одно окно еще не открыто. Пытаться обратиться к процедуре формы в этот момент — все равно что пытаться включить свет в доме, который еще не построен.

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

Шаг 1. Перенос логики поиска в Модуль менеджера

Проанализируем ситуацию: логика проверки уникальности документа (существует ли запись за сегодня по конкретному складу) не должна принадлежать конкретному окну. Это бизнес-логика самого объекта. Лучшее место для неё — Модуль менеджера документа. Процедуры модуля менеджера доступны всегда, для их вызова не нужно открывать форму или создавать объект.

Откроем конфигуратор, найдем документ ТабельСмены, перейдем на закладку "Прочее" и нажмем кнопку "Модуль менеджера". Напишем там экспортную функцию:


Функция НайтиДокументЗаСегодня(ТекущаяДата, ТекущийСклад) Экспорт
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |    ТабельСмены.Ссылка КАК Ссылка
    |ИЗ
    |    Документ.ТабельСмены КАК ТабельСмены
    |ГДЕ
    |    ТабельСмены.Дата МЕЖДУ &НачалоДня И &КонецДня
    |    И ТабельСмены.Склад = &Склад
    |    И НЕ ТабельСмены.ПометкаУдаления";
    
    Запрос.УстановитьПараметр("НачалоДня", НачалоДня(ТекущаяДата));
    Запрос.УстановитьПараметр("КонецДня", КонецДня(ТекущаяДата));
    Запрос.УстановитьПараметр("Склад", ТекущийСклад);
    
    РезультатЗапроса = Запрос.Выполнить();
    
    Если Не РезультатЗапроса.Пустой() Тогда
        Выборка = РезультатЗапроса.Выбрать();
        Выборка.Следующий();
        Возврат Выборка.Ссылка;
    Иначе
        Возврат Справочники.ТабельСмены.ПустаяСсылка();
    КонецЕсли;
    
КонецФункции

Важные моменты: в запросе мы используем ВЫБРАТЬ ПЕРВЫЕ 1 для оптимизации и обязательно передаем параметры (дату и склад), так как в модуле менеджера нет доступа к реквизитам конкретной формы.

Шаг 2. Вызов проверки при старте системы

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

Проанализируем последовательность действий в глобальном модуле:

  1. Система запускается.
  2. Вызывается клиентская процедура.
  3. Определяется текущий склад (например, из настроек пользователя).
  4. Вызывается серверная функция поиска.
  5. Если ссылка найдена — открываем форму существующего документа.

Пример кода в модуле управляемого приложения:


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

Шаг 3. Использование параметров открытия формы

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

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    Если Параметры.Ключ.Пустая() Тогда
        // Это новый документ, можем заполнить значения по умолчанию
        Объект.Склад = Параметры.Склад;
        Объект.Дата = ТекущаяДата();
    КонецЕсли;
    
КонецПроцедуры

Дополнительные рекомендации по производительности

Разберем несколько важных советов, которые помогут избежать ошибок при масштабировании системы:

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

← На главную