Как реализовать авторасчет дополнительного реквизита «Длительность» на основе дат в 1С:Документооборот?

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

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

Анализ задачи и архитектуры дополнительных реквизитов

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

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

Решение 1: Обработка события изменения на форме (версия 2.1)

Для того чтобы пользователь сразу видел результат расчета, нам необходимо «подцепиться» к событиям изменения реквизитов на форме документа. Разберем по шагам, как это сделать.

Во многих конфигурациях 1С:ДО на базе управляемых форм существует предопределенная процедура, которая обрабатывает изменение любого дополнительного реквизита. Рассмотрим код, который необходимо разместить в модуле формы документа:


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

Для корректного обращения к дополнительному реквизиту в старых версиях (где нет поля «Имя для разработчика»), используем поиск по наименованию. Рассмотрим пример функции, которая находит значение и записывает результат:


&НаСервере
Процедура РассчитатьДлительностьНаФорме()
    
    ДопСвойствоДатаНач = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Дата начала");
    ДопСвойствоДатаКон = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Дата окончания");
    ДопСвойствоДлительность = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Длительность");
    
    ДатаНач = Неопределено;
    ДатаКон = Неопределено;
    
    // Ищем значения в табличной части
    Для Каждого СтрокаДопРек из Объект.ДополнительныеРеквизиты Цикл
        Если СтрокаДопРек.Свойство = ДопСвойствоДатаНач Тогда
            ДатаНач = СтрокаДопРек.Значение;
        ИначеЕсли СтрокаДопРек.Свойство = ДопСвойствоДатаКон Тогда
            ДатаКон = СтрокаДопРек.Значение;
        КонецЕсли;
    КонецЦикла;
    
    Если ЗначениеЗаполнено(ДатаНач) И ЗначениеЗаполнено(ДатаКон) Тогда
        // Расчет разницы в днях
        СекундВСутках = 86400;
        КолвоДней = ((КонецДня(ДатаКон) - НачалоДня(ДатаНач)) + 1) / СекундВСутках;
        
        // Записываем результат в доп. реквизит
        Для Каждого СтрокаДопРек из Объект.ДополнительныеРеквизиты Цикл
            Если СтрокаДопРек.Свойство = ДопСвойствоДлительность Тогда
                СтрокаДопРек.Значение = Цел(КолвоДней);
                Прервать;
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
    
КонецПроцедуры

Решение 2: Использование «Имени для разработчика» (версии 2.1.13+)

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

  1. Зайдем в настройки дополнительного реквизита.
  2. В поле «Имя» укажем, например, ДлительностьКомандировки.
  3. В коде будем обращаться к свойству через поиск по этому идентификатору, что защитит код от поломки при переименовании реквизита пользователем.

Решение 3: Расчет с учетом производственного календаря

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


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

Использование такого подхода сделает ваш расчет профессиональным и соответствующим требованиям кадрового учета.

Решение 4: Гарантированный расчет в модуле объекта

Рассчитаем ситуацию, когда документ создается не вручную через форму, а загружается из другой системы (например, из «1С:ЗУП») или создается бизнес-процессом. В этом случае код на форме не сработает. Чтобы данные всегда были актуальны, добавим логику в модуль объекта документа в процедуру ПередЗаписью.

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

Особенности реализации в 1С:Документооборот 3.0

Если вы работаете в версии 3.0, обратите внимание на механизм «Скриптов тематик» и «Правил обработки». В новой архитектуре 1С:ДО предоставляет возможность писать скрипты на языке 1С непосредственно в пользовательском режиме (в справочнике настроек), которые будут выполняться при изменении данных. Это позволяет избежать изменения конфигурации и снятия её с поддержки, что значительно упрощает дальнейшие обновления программы.

Рассмотрим пример логики для скрипта в 3.0:

Рекомендации по контролю целостности

При внедрении авторасчета обязательно учтите следующие моменты:

  1. Часовые пояса: всегда используйте функцию НачалоДня() для обеих дат, иначе разница между 23:00 первого дня и 01:00 следующего может быть посчитана неверно.
  2. Пустые значения: если одна из дат очищена пользователем, реквизит «Длительность» также должен очищаться или обнуляться.
  3. Тип данных: убедитесь, что дополнительный реквизит имеет тип Число с достаточной точностью (обычно 10.0, если не используются дробные дни).

Таким образом, мы разобрали основные способы автоматизации расчета длительности. Наиболее эффективным методом для версии 2.1 является сочетание кода в модуле формы (для интерактивности) и в модуле объекта (для надежности), а для версии 3.0 — использование встроенных механизмов скриптования.

← На главную