В процессе автоматизации документооборота, особенно в части оформления командировок, часто возникает задача минимизировать ручной ввод данных. Одной из таких задач является автоматический расчет количества дней командировки (реквизит «Длительность») сразу после того, как пользователь указал даты начала и окончания. Рассмотрим подробно, как реализовать этот функционал в различных версиях «1С:Документооборот» (1С:ДО), какие программные методы использовать и как обеспечить надежность данных.
Прежде чем приступать к написанию кода, проанализируем, как хранятся дополнительные реквизиты. В системе 1С:ДО они не являются полями основной таблицы (как, например, Дата или РегистрационныйНомер), а хранятся в подчиненной табличной части ДополнительныеРеквизиты. Каждый элемент этой таблицы состоит из пары: Свойство (ссылка на план видов характеристик) и Значение.
Сложность заключается в том, что стандартными настройками (через интерфейс) можно задать только видимость или доступность. Для вычислений нам потребуется вмешательство в программный код формы или объекта.
Для того чтобы пользователь сразу видел результат расчета, нам необходимо «подцепиться» к событиям изменения реквизитов на форме документа. Разберем по шагам, как это сделать.
Во многих конфигурациях 1С:ДО на базе управляемых форм существует предопределенная процедура, которая обрабатывает изменение любого дополнительного реквизита. Рассмотрим код, который необходимо разместить в модуле формы документа:
&НаКлиенте
Процедура Подключаемый_ПриИзмененииДополнительногоРеквизита(Элемент)
// Определяем имена наших реквизитов (как они заданы в системе)
ИмяРеквизитаНачало = "ДатаНачалаКомандировки";
ИмяРеквизитаКонец = "ДатаОкончанияКомандировки";
ИмяРеквизитаДлительность = "Длительность";
// Получаем текущие данные формы
ТекущийОбъект = ЭтаФорма.Объект;
// Выполняем расчет, если заполнены обе даты
// В данном примере предполагается, что даты - это стандартные реквизиты или доп.реквизиты
РассчитатьДлительностьНаФорме();
КонецПроцедуры
Для корректного обращения к дополнительному реквизиту в старых версиях (где нет поля «Имя для разработчика»), используем поиск по наименованию. Рассмотрим пример функции, которая находит значение и записывает результат:
&НаСервере
Процедура РассчитатьДлительностьНаФорме()
ДопСвойствоДатаНач = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Дата начала");
ДопСвойствоДатаКон = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Дата окончания");
ДопСвойствоДлительность = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Длительность");
ДатаНач = Неопределено;
ДатаКон = Неопределено;
// Ищем значения в табличной части
Для Каждого СтрокаДопРек из Объект.ДополнительныеРеквизиты Цикл
Если СтрокаДопРек.Свойство = ДопСвойствоДатаНач Тогда
ДатаНач = СтрокаДопРек.Значение;
ИначеЕсли СтрокаДопРек.Свойство = ДопСвойствоДатаКон Тогда
ДатаКон = СтрокаДопРек.Значение;
КонецЕсли;
КонецЦикла;
Если ЗначениеЗаполнено(ДатаНач) И ЗначениеЗаполнено(ДатаКон) Тогда
// Расчет разницы в днях
СекундВСутках = 86400;
КолвоДней = ((КонецДня(ДатаКон) - НачалоДня(ДатаНач)) + 1) / СекундВСутках;
// Записываем результат в доп. реквизит
Для Каждого СтрокаДопРек из Объект.ДополнительныеРеквизиты Цикл
Если СтрокаДопРек.Свойство = ДопСвойствоДлительность Тогда
СтрокаДопРек.Значение = Цел(КолвоДней);
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
В более свежих версиях 1С:ДО у дополнительных реквизитов появилось поле «Имя» (для разработчика). Это значительно упрощает код, так как нам больше не нужно использовать ненадежный поиск по строковому наименованию НайтиПоНаименованию. Проанализируем, как изменится подход:
ДлительностьКомандировки.Зачастую бизнес требует рассчитывать не календарные дни, а рабочие. Простое вычитание дат здесь не поможет. Выясним, как использовать системные механизмы для учета выходных. В 1С есть справочник ПроизводственныеКалендари. Проанализируем функцию для расчета рабочих дней:
Функция ПолучитьРабочиеДни(ДатаНач, ДатаКон)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(ДанныеПроизводственногоКалендаря.Дата) КАК КолвоДней
|ИЗ
| РегистрСведений.ДанныеПроизводственногоКалендаря КАК ДанныеПроизводственногоКалендаря
|ГДЕ
| ДанныеПроизводственногоКалендаря.Дата МЕЖДУ &ДатаНач И &ДатаКон
| И ДанныеПроизводственногоКалендаря.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)";
Запрос.УстановитьПараметр("ДатаНач", НачалоДня(ДатаНач));
Запрос.УстановитьПараметр("ДатаКон", КонецДня(ДатаКон));
Результат = Запрос.Выполнить().Выгрузить();
Возврат ?(Результат.Количество() > 0, Результат[0].КолвоДней, 0);
КонецФункции
Использование такого подхода сделает ваш расчет профессиональным и соответствующим требованиям кадрового учета.
Рассчитаем ситуацию, когда документ создается не вручную через форму, а загружается из другой системы (например, из «1С:ЗУП») или создается бизнес-процессом. В этом случае код на форме не сработает. Чтобы данные всегда были актуальны, добавим логику в модуль объекта документа в процедуру ПередЗаписью.
Важный нюанс: при записи объекта на сервере необходимо проверять, изменились ли даты, чтобы не выполнять лишних вычислений. Также рекомендуется установить для доп. реквизита «Длительность» признак Только просмотр на форме, чтобы пользователи не правили рассчитанное значение вручную, создавая риск логических ошибок.
Если вы работаете в версии 3.0, обратите внимание на механизм «Скриптов тематик» и «Правил обработки». В новой архитектуре 1С:ДО предоставляет возможность писать скрипты на языке 1С непосредственно в пользовательском режиме (в справочнике настроек), которые будут выполняться при изменении данных. Это позволяет избежать изменения конфигурации и снятия её с поддержки, что значительно упрощает дальнейшие обновления программы.
Рассмотрим пример логики для скрипта в 3.0:
ДополнительныеРеквизиты и присвоения значения.При внедрении авторасчета обязательно учтите следующие моменты:
НачалоДня() для обеих дат, иначе разница между 23:00 первого дня и 01:00 следующего может быть посчитана неверно.Число с достаточной точностью (обычно 10.0, если не используются дробные дни).Таким образом, мы разобрали основные способы автоматизации расчета длительности. Наиболее эффективным методом для версии 2.1 является сочетание кода в модуле формы (для интерактивности) и в модуле объекта (для надежности), а для версии 3.0 — использование встроенных механизмов скриптования.