Как сохранить значение в дополнительной колонке документа «Начисление зарплаты и взносов» при пересчете сотрудника в ЗУП 3.1?

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом
← На главную

При разработке в среде 1С:Зарплата и управление персоналом 3.1 программисты часто сталкиваются с задачей расширения типового функционала. Одной из популярных задач является добавление пользовательских колонок в табличные части основных документов, таких как Начисление зарплаты и взносов. Однако стандартные механизмы программы могут преподнести сюрприз: при нажатии кнопки «Пересчитать сотрудника» все данные, введенные вручную в новую колонку, бесследно исчезают. Разберем подробно, почему это происходит и как правильно реализовать сохранение данных через расширение конфигурации.

Почему данные обнуляются? Проанализируем ситуацию

Многие начинающие разработчики полагают, что пересчет строки в документе — это просто обновление числовых показателей (результата расчета) в уже существующих строках. На самом деле в ЗУП 3.1 (особенно в ранних релизах, таких как 3.1.1) реализован механизм полного перезаполнения. Рассмотрим, что происходит «под капотом» системы при вызове команды пересчета:

  1. Программа определяет список строк, относящихся к выбранному сотруднику.
  2. Система физически удаляет эти строки из коллекции табличной части Начисления.
  3. «Движок» расчета формирует новые наборы данных на основании кадровых приказов, графиков работы и настроенных начислений.
  4. В табличную часть добавляются новые строки.

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

Вариант 1. Кэширование данных перед пересчетом (через расширение)

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

Обычно команда пересчета на форме документа вызывает серверную процедуру. Нам необходимо создать в расширении два метода с аннотациями &Перед и &После. Рассмотрим примерный алгоритм реализации:

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


&Перед("ПересчитатьСотрудникаСервер")
Процедура Расш1_ПередПересчитатьСотрудникаСервер(Сотрудник, ИдентификаторСтроки)
    
    // Создаем таблицу для хранения «старых» данных
    ТЗ_Буфер = Новый ТаблицаЗначений;
    ТЗ_Буфер.Колонки.Добавить("ВидРасчета");
    ТЗ_Буфер.Колонки.Добавить("МойРеквизит"); // Ваше кастомное поле
    
    // Находим строки сотрудника и сохраняем значение
    ПараметрыОтбора = Новый Структура("Сотрудник", Сотрудник);
    НайденныеСтроки = Объект.Начисления.НайтиСтроки(ПараметрыОтбора);
    
    Для Каждого СтрокаТЧ Из НайденныеСтроки Цикл
        НоваяЗапись = ТЗ_Буфер.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяЗапись, СтрокаТЧ);
    КонецЦикла;
    
    // Сохраняем ТЗ в реквизит формы или временное хранилище для доступа в &После
    ЭтотОбъект.ПараметрыПересчета.Вставить("БуферДанных", ТЗ_Буфер);
    
КонецПроцедуры

Шаг 2. Восстановление данных. В процедуре &После мы ищем новые созданные строки и сопоставляем их с нашим буфером по ключевым полям (например, по Сотрудник и ВидРасчета).


&После("ПересчитатьСотрудникаСервер")
Процедура Расш1_ПослеПересчитатьСотрудникаСервер(Сотрудник, ИдентификаторСтроки)
    
    ТЗ_Буфер = Неопределено;
    Если Не ЭтотОбъект.ПараметрыПересчета.Свойство("БуферДанных", ТЗ_Буфер) Тогда
        Возврат;
    КонецЕсли;
    
    // Обходим новые строки и восстанавливаем значения
    ПараметрыОтбора = Новый Структура("Сотрудник", Сотрудник);
    НовыеСтроки = Объект.Начисления.НайтиСтроки(ПараметрыОтбора);
    
    Для Каждого СтрокаТЧ Из НовыеСтроки Цикл
        ОтборБуфера = Новый Структура("ВидРасчета", СтрокаТЧ.ВидРасчета);
        СтрокиБуфера = ТЗ_Буфер.НайтиСтроки(ОтборБуфера);
        
        Если СтрокиБуфера.Количество() > 0 Тогда
            СтрокаТЧ.МойРеквизит = СтрокиБуфера[0].МойРеквизит;
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

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

Вариант 2. Использование механизмов расчета зарплаты (Архитектурный подход)

Проанализируем ситуацию глубже. Если ваша ячейка должна содержать данные, которые влияют на расчет или просто должны там храниться, возможно, добавление колонки в ТЧ — не лучший путь. В 1С:ЗУП 3.1 предусмотрен механизм показателей расчета зарплаты.

Если данные в ячейке — это число, которое должен вводить пользователь, лучше сделать следующее:

  1. Создать новый Показатель расчета зарплаты (Настройка -> Показатели расчета зарплаты). Установить его как «Используется только в месяце введения».
  2. Добавить этот показатель в формулу соответствующего Начисления.
  3. После этого в документе Начисление зарплаты и взносов в табличной части Начисления автоматически появится колонка для ввода этого показателя.

Преимущество этого метода: Данные будут сохраняться типовым механизмом. При пересчете программа сама увидит введенный показатель и подставит его в расчет. Вам не придется писать ни одной строчки кода в расширении.

Вариант 3. Использование отдельной табличной части

Если данные в вашей колонке носят справочный характер и не участвуют напрямую в математических формулах, рассмотрите вариант создания собственной табличной части в расширении документа.

Поскольку типовой механизм пересчета очищает только стандартную коллекцию Начисления, ваша кастомная ТЧ останется нетронутой. Вам останется только синхронизировать отображение данных на форме, связав строки основной ТЧ и вашей новой ТЧ по индексу или уникальному ключу сотрудника. Это более трудоемкий, но архитектурно «чистый» способ, не нарушающий логику работы типовых процедур обновления.

Подведем итоги

Выясним причину ошибки: данные обнуляются из-за того, что ЗУП 3.1 пересоздает строки «с чистого листа». Для решения задачи мы можем либо программно кэшировать данные в расширении, используя методы &Перед и &После, либо использовать типовой функционал показателей, что является более предпочтительным с точки зрения стабильности системы. Выбор метода зависит от того, должен ли ваш реквизит участвовать в формуле расчета или он просто выполняет роль комментария/метки.

← На главную