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