Почему не сохраняются показатели расчета зарплаты при программном заполнении документа в 1С:ЗУП 3.1?

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

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

Разберем детально, как устроена внутренняя архитектура хранения показателей расчета зарплаты, выясним причину такого поведения и рассмотрим корректный программный алгоритм заполнения документа.

Архитектурные особенности хранения показателей в ЗУП 3.1

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

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

Связь между строкой начисления и подчиненными строками показателей осуществляется не по номеру строки, а через специальный числовой реквизит ИдентификаторСтрокиВидаРасчета. Каждая строка начисления имеет свой уникальный идентификатор, и все относящиеся к ней показатели должны содержать точно такое же значение в поле ИдентификаторСтрокиВидаРасчета.

Основные причины исчезновения показателей при записи

Проанализируем ключевые ошибки, приводящие к потере данных:

  1. Не передана ссылка на показатель: если в строке табличной части Показатели заполнено значение, но в реквизит Показатель передано значение Неопределено или пустая ссылка, типовой механизм валидации перед записью считает строку некорректной и очищает её.
  2. Несовпадение идентификаторов строк: значение ИдентификаторСтрокиВидаРасчета в ТЧ Начисления не совпадает с аналогичным полем в ТЧ Показатели. В таком случае показатель становится «сиротой» и удаляется подсистемой расчета.
  3. Сброс типовым движком расчета: в событии ПередЗаписью запускается пересчет документа. Если для добавленных строк не установлены флаги фиксации (ФиксРасчет = Истина, ФиксЗаполнение = Истина, ФиксРасчетВремени = Истина), программа пытается рассчитать показатели заново по формуле вида расчета и перезаписывает введенные данные.
  4. Особенности динамических колонок формы: если заполнение выполняется на клиенте в контексте открытой формы, форма отображает показатели через динамически создаваемые реквизиты. При прямой модификации ТЧ без инициализации элементов формы при сохранении может произойти перезапись данных пустыми значениями из интерфейса.

Алгоритм правильного программного заполнения документа

Разберем по шагам, как правильно подготовить структуру данных и заполнить документ программно.

Сначала получим список показателей, используемых в начислении, с помощью запроса к плану видов расчета:


Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ВидНачисления", ВыбранныйВидНачисления);
Запрос.Текст = 
    "ВЫБРАТЬ
    |    НачисленияПоказатели.Показатель КАК Показатель,
    |    НачисленияПоказатели.Ссылка КАК ВидНачисления,
    |    НачисленияПоказатели.Ссылка.Рассчитывается КАК Рассчитывается
    |ИЗ
    |    ПланВидовРасчета.Начисления.Показатели КАК НачисленияПоказатели
    |ГДЕ
    |    НачисленияПоказатели.Ссылка = &ВидНачисления
    |    И НачисленияПоказатели.ОсновнойПоказатель";

ТаблицаПоказателей = Запрос.Выполнить().Выгрузить();
ТаблицаПоказателей.Индексы.Добавить("ВидНачисления");

Далее рассмотрим пример заполнения табличных частей создаваемого документа с обязательной установкой связи по идентификаторам и флагов фиксации:


// Инициализируем счетчик идентификатора строк
ИдентификаторСтрокиВидаРасчета = 0;

Для Каждого СтрДанных Из ТаблицаИсходныхДанных Цикл

    ИдентификаторСтрокиВидаРасчета = ИдентификаторСтрокиВидаРасчета + 1;
    
    // 1. Заполняем основную строку начисления
    СтрНачисление = ДокументОбъект.Начисления.Добавить();
    СтрНачисление.Сотрудник = СтрДанных.Сотрудник;
    СтрНачисление.Подразделение = СтрДанных.Подразделение;
    СтрНачисление.Результат = СтрДанных.Сумма;
    СтрНачисление.ИдентификаторСтрокиВидаРасчета = ИдентификаторСтрокиВидаРасчета;
    
    СтрНачисление.ДатаНачала = НачалоМесяца(ДокументОбъект.ПериодРегистрации);
    СтрНачисление.ДатаОкончания = КонецМесяца(ДокументОбъект.ПериодРегистрации);
    СтрНачисление.ПериодДействия = НачалоМесяца(ДокументОбъект.ПериодРегистрации);
    СтрНачисление.ПериодРегистрацииВремени = СтрНачисление.ДатаНачала;
    СтрНачисление.ПериодРегистрацииНормыВремени = НачалоМесяца(ДокументОбъект.ПериодРегистрации);
    
    // Обязательные флаги, предотвращающие сброс расчета при записи
    СтрНачисление.ФиксРасчет = Истина;
    СтрНачисление.ФиксЗаполнение = Истина;
    СтрНачисление.ФиксРасчетВремени = Истина;
    
    СтрНачисление.ВидУчетаВремени = Справочники.ВидыИспользованияРабочегоВремени.Явка;
    
    // 2. Заполняем показатели расчета для данной строки
    Для Каждого СтрПоказатель Из ТаблицаПоказателей Цикл
        СтрПок = ДокументОбъект.Показатели.Добавить();
        СтрПок.ИдентификаторСтрокиВидаРасчета = ИдентификаторСтрокиВидаРасчета;
        СтрПок.Показатель = СтрПоказатель.Показатель; // Ссылка на СправочникСсылка.ПоказателиРасчетаЗарплаты
        СтрПок.Значение = СтрДанных.ЗначениеПоказателя;
    КонецЦикла;
    
    // 3. Заполняем аналитику распределения
    СтрРаспределение = ДокументОбъект.РаспределениеРезультатовНачислений.Добавить();
    СтрРаспределение.ИдентификаторСтроки = ИдентификаторСтрокиВидаРасчета;
    СтрРаспределение.Территория = ДокументОбъект.Подразделение;
    СтрРаспределение.Результат = СтрДанных.Сумма;
    
    // 4. Заполняем список физических лиц
    СтрФЛ = ДокументОбъект.ФизическиеЛица.Добавить();
    СтрФЛ.ФизическоеЛицо = СтрДанных.ФизическоеЛицо;

КонецЦикла;

Чек-лист для проверки перед сохранением

Если показатели расчета все равно не сохраняются, проверьте следующие моменты:

  1. Тип значения в поле Показатель: убедитесь в отладчике, что в ТЧ Показатели передается валидная ссылка типа СправочникСсылка.ПоказателиРасчетаЗарплаты, а не строка с наименованием или пустое значение.
  2. Связка идентификаторов: проверьте, что значение ИдентификаторСтрокиВидаРасчета инкрементируется для каждого начисления и строго совпадает в ТЧ Начисления и подчиненной строке ТЧ Показатели.
  3. Настройка формулы начисления: показатель должен входить в формулу начисления и иметь признак ввода значения в документе (разовый показатель).
  4. Флаги фиксации: проверьте наличие флага ФиксРасчет = Истина в строке начисления, чтобы предотвратить перезапуск типового алгоритма расчета перед записью объекта.
← На главную