В процессе сопровождения систем 1С:ERP Управление предприятием или 1С:Зарплата и управление персоналом 3.1 часто возникают задачи по кастомизации типовых документов под требования конкретного отдела кадров или бухгалтерии. Рассмотрим две классические задачи: установку контроля соответствия дат в документе БольничныйЛист и автоматическое заполнение параметров расчета в документе ПриемНаРаботу.
Для реализации этих задач мы будем использовать механизм расширений конфигурации, так как это позволяет сохранить типовую конфигурацию на поддержке и минимизировать риски при обновлении системы.
Суть задачи заключается в том, чтобы система выдавала предупреждение или вопрос пользователю, если месяц даты окончания нетрудоспособности не совпадает с месяцем периода регистрации документа. Это критично для корректного отражения начислений в налоговых и учетных периодах.
Разберем по шагам, почему обычный метод Вопрос() не сработает в процедуре ПередЗаписью на сервере. В управляемом приложении 1С разделяет выполнение кода на клиентский и серверный контексты. Серверный код не может прерывать выполнение для ожидания ответа пользователя. Поэтому нам необходимо организовать «двухэтапную» проверку.
Проанализируем алгоритм реализации в расширении для формы документа БольничныйЛист:
ПередЗаписью на клиенте.НачалоМесяца(), которая позволяет игнорировать число и время, сравнивая только начало периода.ПоказатьВопрос().Посмотрим на пример программного кода, который реализует данную логику:
&НаКлиенте
Процедура Расш1_ПередЗаписьюПосле(Отказ, ПараметрыЗаписи)
// Проверяем, что даты заполнены
Если ЗначениеЗаполнено(Объект.ДатаОкончания) И ЗначениеЗаполнено(Объект.ПериодРегистрации) Тогда
// Сравниваем начала месяцев
Если НачалоМесяца(Объект.ДатаОкончания) <> НачалоМесяца(Объект.ПериодРегистрации) Тогда
// Если флаг подтверждения еще не установлен в параметрах записи
Если Не ПараметрыЗаписи.Свойство("ПодтвержденоНесовпадениеМесяцев") Тогда
Отказ = Истина;
Оповещение = Новый ОписаниеОповещения("ЗавершитьЗаписьПослеВопроса", ЭтотОбъект, ПараметрыЗаписи);
ПоказатьВопрос(Оповещение, "Месяц даты окончания не совпадает с месяцем периода регистрации. Продолжить запись?", РежимДиалогаВопрос.ДаНет);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ЗавершитьЗаписьПослеВопроса(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
// Добавляем признак того, что пользователь согласился
ДополнительныеПараметры.Вставить("ПодтвержденоНесовпадениеМесяцев", Истина);
ЭтотОбъект.Записать(ДополнительныеПараметры);
КонецЕсли;
КонецПроцедуры
Важный момент: использование метода НачалоМесяца гораздо надежнее, чем простое сравнение свойства .Месяц у даты, так как прямое обращение к месяцу вернет число от 1 до 12, и программа может ошибочно посчитать даты за разные годы (например, декабрь 2023 и декабрь 2024) одинаковыми.
Вторая задача требует изменения логики заполнения документа ПриемНаРаботу. Нам необходимо, чтобы при выборе определенного графика работы автоматически устанавливался ПорядокПересчета стоимости часа.
Разберем ситуацию: если выбран график «Основной пятидневка», устанавливаем значение «По норме графика», во всех остальных случаях — «По среднемесячному количеству часов/дней».
Для реализации этой задачи лучше всего использовать обработчик события ПриИзменении для реквизита ГрафикРаботы на форме документа. Это позволит пользователю сразу увидеть результат работы алгоритма.
Проанализируем использование перечислений. В системе 1С порядок пересчета хранится в объекте Перечисления.ПорядокПересчетаСтоимостиЧаса. Нам понадобятся значения ПоНормеГрафика и ПоСреднемесячнойНорме.
Рассмотрим пример кода для расширения формы документа:
&НаКлиенте
Процедура Расш1_ГрафикРаботыПриИзмененииПосле(Элемент)
// Выясним причину изменения и установим порядок пересчета
Если ЗначениеЗаполнено(Объект.ГрафикРаботы) Тогда
// Получаем наименование графика для условия
// Внимание: поиск по наименованию считается "хрупким",
// лучше использовать дополнительные реквизиты графика
НаименованиеГрафика = СокрЛП(Объект.ГрафикРаботы.Наименование);
Если НаименованиеГрафика = "Основной пятидневка" Тогда
Объект.ПорядокПересчета = ПредопределенноеЗначение("Перечисление.ПорядокПересчетаСтоимостиЧаса.ПоНормеГрафика");
Иначе
Объект.ПорядокПересчета = ПредопределенноеЗначение("Перечисление.ПорядокПересчетаСтоимостиЧаса.ПоСреднемесячнойНорме");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Выясним некоторые технические нюансы. В документе ПриемНаРаботу поле ПорядокПересчета может быть недоступно для редактирования, если в настройках расчета зарплаты (раздел Настройка — Расчет зарплаты) установлен фиксированный порядок для всей организации. Чтобы наша доработка имела смысл, в настройках должна быть активна опция «При изменении нормы времени в течение месяца».
При написании кода в расширениях всегда придерживайтесь следующих правил:
&После или &Вместо крайне осторожно. Для простых проверок идеально подходит &После, так как она не заменяет типовую логику, а дополняет её.ЗначениеЗаполнено() для ссылочных полей, чтобы избежать ошибок при обращении к свойствам пустой ссылки (например, Объект.ГрафикРаботы.Наименование вызовет ошибку, если график не выбран).ПриемНаРаботу может быть как на одного сотрудника, так и списком (ПриемНаРаботуСписком). Если в вашей компании используются оба вида, код необходимо продублировать или вынести в общий модуль расширения, учитывая, что в списочном документе данные хранятся в табличной части.Таким образом, мы рассмотрели, как с помощью нескольких строк кода и механизма расширений можно значительно упростить работу кадровой службы, автоматизировав рутинные проверки и заполнение данных в 1С:ERP.