При разработке внешних обработок и алгоритмов автозаполнения расчетных документов в конфигурации «1С:Зарплата и управление персоналом 3.1» (например, документа Разовое начисление) разработчики часто сталкиваются с ситуацией: данные визуально присутствуют в форме или передаются в объект, но в момент записи или проведения документа значения показателей расчета бесследно исчезают или сбрасываются.
Разберем детально, как устроена внутренняя архитектура хранения показателей расчета зарплаты, выясним причину такого поведения и рассмотрим корректный программный алгоритм заполнения документа.
В отличие от простых учетных документов, в расчетных документах 1С:ЗУП данные о начислениях разделены между несколькими связанными табличными частями:
Связь между строкой начисления и подчиненными строками показателей осуществляется не по номеру строки, а через специальный числовой реквизит ИдентификаторСтрокиВидаРасчета. Каждая строка начисления имеет свой уникальный идентификатор, и все относящиеся к ней показатели должны содержать точно такое же значение в поле ИдентификаторСтрокиВидаРасчета.
Проанализируем ключевые ошибки, приводящие к потере данных:
Показатели заполнено значение, но в реквизит Показатель передано значение Неопределено или пустая ссылка, типовой механизм валидации перед записью считает строку некорректной и очищает её.ИдентификаторСтрокиВидаРасчета в ТЧ Начисления не совпадает с аналогичным полем в ТЧ Показатели. В таком случае показатель становится «сиротой» и удаляется подсистемой расчета.ПередЗаписью запускается пересчет документа. Если для добавленных строк не установлены флаги фиксации (ФиксРасчет = Истина, ФиксЗаполнение = Истина, ФиксРасчетВремени = Истина), программа пытается рассчитать показатели заново по формуле вида расчета и перезаписывает введенные данные.Разберем по шагам, как правильно подготовить структуру данных и заполнить документ программно.
Сначала получим список показателей, используемых в начислении, с помощью запроса к плану видов расчета:
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ВидНачисления", ВыбранныйВидНачисления);
Запрос.Текст =
"ВЫБРАТЬ
| НачисленияПоказатели.Показатель КАК Показатель,
| НачисленияПоказатели.Ссылка КАК ВидНачисления,
| НачисленияПоказатели.Ссылка.Рассчитывается КАК Рассчитывается
|ИЗ
| ПланВидовРасчета.Начисления.Показатели КАК НачисленияПоказатели
|ГДЕ
| НачисленияПоказатели.Ссылка = &ВидНачисления
| И НачисленияПоказатели.ОсновнойПоказатель";
ТаблицаПоказателей = Запрос.Выполнить().Выгрузить();
ТаблицаПоказателей.Индексы.Добавить("ВидНачисления");
Далее рассмотрим пример заполнения табличных частей создаваемого документа с обязательной установкой связи по идентификаторам и флагов фиксации:
// Инициализируем счетчик идентификатора строк
ИдентификаторСтрокиВидаРасчета = 0;
Для Каждого СтрДанных Из ТаблицаИсходныхДанных Цикл
ИдентификаторСтрокиВидаРасчета = ИдентификаторСтрокиВидаРасчета + 1;
// 1. Заполняем основную строку начисления
СтрНачисление = ДокументОбъект.Начисления.Добавить();
СтрНачисление.Сотрудник = СтрДанных.Сотрудник;
СтрНачисление.Подразделение = СтрДанных.Подразделение;
СтрНачисление.Результат = СтрДанных.Сумма;
СтрНачисление.ИдентификаторСтрокиВидаРасчета = ИдентификаторСтрокиВидаРасчета;
СтрНачисление.ДатаНачала = НачалоМесяца(ДокументОбъект.ПериодРегистрации);
СтрНачисление.ДатаОкончания = КонецМесяца(ДокументОбъект.ПериодРегистрации);
СтрНачисление.ПериодДействия = НачалоМесяца(ДокументОбъект.ПериодРегистрации);
СтрНачисление.ПериодРегистрацииВремени = СтрНачисление.ДатаНачала;
СтрНачисление.ПериодРегистрацииНормыВремени = НачалоМесяца(ДокументОбъект.ПериодРегистрации);
// Обязательные флаги, предотвращающие сброс расчета при записи
СтрНачисление.ФиксРасчет = Истина;
СтрНачисление.ФиксЗаполнение = Истина;
СтрНачисление.ФиксРасчетВремени = Истина;
СтрНачисление.ВидУчетаВремени = Справочники.ВидыИспользованияРабочегоВремени.Явка;
// 2. Заполняем показатели расчета для данной строки
Для Каждого СтрПоказатель Из ТаблицаПоказателей Цикл
СтрПок = ДокументОбъект.Показатели.Добавить();
СтрПок.ИдентификаторСтрокиВидаРасчета = ИдентификаторСтрокиВидаРасчета;
СтрПок.Показатель = СтрПоказатель.Показатель; // Ссылка на СправочникСсылка.ПоказателиРасчетаЗарплаты
СтрПок.Значение = СтрДанных.ЗначениеПоказателя;
КонецЦикла;
// 3. Заполняем аналитику распределения
СтрРаспределение = ДокументОбъект.РаспределениеРезультатовНачислений.Добавить();
СтрРаспределение.ИдентификаторСтроки = ИдентификаторСтрокиВидаРасчета;
СтрРаспределение.Территория = ДокументОбъект.Подразделение;
СтрРаспределение.Результат = СтрДанных.Сумма;
// 4. Заполняем список физических лиц
СтрФЛ = ДокументОбъект.ФизическиеЛица.Добавить();
СтрФЛ.ФизическоеЛицо = СтрДанных.ФизическоеЛицо;
КонецЦикла;
Если показатели расчета все равно не сохраняются, проверьте следующие моменты:
Показатель: убедитесь в отладчике, что в ТЧ Показатели передается валидная ссылка типа СправочникСсылка.ПоказателиРасчетаЗарплаты, а не строка с наименованием или пустое значение.ИдентификаторСтрокиВидаРасчета инкрементируется для каждого начисления и строго совпадает в ТЧ Начисления и подчиненной строке ТЧ Показатели.ФиксРасчет = Истина в строке начисления, чтобы предотвратить перезапуск типового алгоритма расчета перед записью объекта.