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