Как проверить существование документа на текущую дату перед записью в 1С

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

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

Проблема прямого сравнения дат

Часто начинающие разработчики пытаются сравнить дату документа с текущей датой напрямую, используя операторы равенства. Рассмотрим, почему это не работает. В системе 1С тип Дата всегда содержит время с точностью до секунды. Если вы напишете Если ДатаДокумента = ТекущаяДата() Тогда, условие выполнится только в том случае, если обе даты совпадают до секунды, что практически невозможно.

Для корректного поиска документов «за сегодня» необходимо проверять вхождение даты документа в интервал от 00:00:00 до 23:59:59 нужного дня.

Использование запроса для проверки дублей

Наиболее правильным и производительным способом проверки является использование объекта Запрос. Мы обратимся к базе данных и выясним, существуют ли уже документы с таким же сотрудником в указанном диапазоне дат.

Разберем реализацию в процедуре ПередЗаписью модуля документа. Этот обработчик удобен тем, что позволяет прервать запись, установив параметр Отказ в значение Истина.

Рассмотрим пример кода:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)

    // Проверяем только при создании нового или изменении существующего документа
    // Если это новый документ, нам нужно убедиться, что такого еще нет.
    // Если мы редактируем старый, нужно исключить саму «себя» из проверки.

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

    // Устанавливаем границы дня для поиска
    Запрос.УстановитьПараметр("НачалоДня", НачалоДня(Дата));
    Запрос.УстановитьПараметр("КонецДня", КонецДня(Дата));
    Запрос.УстановитьПараметр("Сотрудник", Сотрудник);
    Запрос.УстановитьПараметр("ТекущаяСсылка", Ссылка);

    РезультатЗапроса = Запрос.Выполнить();

    Если Не РезультатЗапроса.Пустой() Тогда
        Отказ = Истина;
        Сообщить("Внимание! Сотрудник " + Сотрудник + " уже зарегистрирован в табеле на текущую дату!");
    КонецЕсли;

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

Разбор ключевых моментов кода

Проанализируем, какие механизмы мы использовали в данном решении:

  1. Конструкция МЕЖДУ: Мы используем функции НачалоДня и КонецДня. Это гарантирует, что запрос увидит все документы, созданные с 00:00:00 до 23:59:59 указанной даты, независимо от того, в какую секунду они были записаны.
  2. ВЫБРАТЬ ПЕРВЫЕ 1: Нам не нужно знать количество документов или их список. Достаточно факта наличия хотя бы одного. Это ускоряет работу базы данных.
  3. Исключение текущей ссылки: Условие ТабельСмены.Ссылка <> &ТекущаяСсылка критически важно. Без него, если вы откроете уже существующий документ и нажмете «Записать», программа найдет в базе этот же самый документ и запретит его сохранение, посчитав дублем.
  4. Параметр Отказ: Установка Отказ = Истина — это стандартный способ 1С отменить транзакцию записи и оставить форму открытой для исправлений.

Особенности работы в Обычных формах

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

Если бы мы работали в Управляемых формах, нам пришлось бы использовать префикс Объект. (например, Объект.Сотрудник), но в данном контексте это приведет к ошибке «Переменная не определена», о чем и упоминалось в обсуждении на форуме.

Альтернативный подход: Использование Регистров сведений

Хотя проверка по документам работает, профессиональным стандартом в 1С считается использование Регистров сведений. Давайте выясним причину, по которой это предпочтительнее:

Документы — это тяжелые объекты. Когда документов в базе станет десятки тысяч, запрос по их таблице может замедлиться. Регистр сведений специально оптимизирован для хранения состояний. Мы можем создать регистр ЗанятостьСотрудников с измерениями Сотрудник и Дата (периодичность — День).

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

Рекомендации по улучшению интерфейса

Чтобы сделать работу пользователя более комфортной, мы можем добавить проверку не только в момент нажатия кнопки «ОК», но и сразу при выборе сотрудника в форме документа. Рассмотрим, как это реализовать:

В модуле формы для элемента управления «Сотрудник» создадим событие ПриИзменении:


Процедура СотрудникПриИзменении(Элемент)
    // Здесь можно вызвать аналогичный запрос. 
    // Если документ уже существует, выдать предупреждение пользователю сразу, 
    // не дожидаясь заполнения всей формы.
КонецПроцедуры

Это сэкономит время сотрудника, так как он мгновенно узнает об ошибке и не будет тратить время на заполнение остальных реквизитов (таких как «Объект», «Оклад» и т.д.), которые всё равно не удастся сохранить.

Резюмируем: Для надежной проверки документов на дубли всегда используйте запросы с четким указанием границ периода (день) и обязательным исключением ссылки текущего документа. Это обеспечит стабильную работу программы и целостность ваших данных.

← На главную