Как исправить ошибку «Запись не соответствует отбору» при записи в регистр «Трудовая деятельность физических лиц»

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

При программном переносе данных или автоматическом заполнении записей в конфигурации 1С:Зарплата и управление персоналом 3.1 разработчики часто сталкиваются с системной ошибкой: «Запись не соответствует отбору». Проблема проявляется наиболее остро при работе с регистром сведений ТрудоваяДеятельностьФизическихЛиц, когда мы пытаемся добавить вторую и последующие записи для одного и того же физического лица, используя объект МенеджерЗаписи.

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

Выясняем причину возникновения ошибки

Рассмотрим стандартную ситуацию. Допустим, нам нужно перенести сведения о трудовой деятельности сотрудника. У записи есть два ключевых измерения: ФизическоеЛицо и НомерПоПорядку. Мы создаем МенеджерЗаписи, заполняем измерения и пытаемся выполнить метод Записать(). Первая запись (где номер равен 1) проходит успешно, но на второй записи система выдает ошибку соответствия отбору.

Проанализируем ситуацию: когда вызывается метод Записать() у объекта МенеджерЗаписи, платформа 1С автоматически устанавливает отбор по всем измерениям, которые указаны в менеджере. В нашем случае это конкретное физлицо и номер записи (например, 2). Однако перед фактической записью в базу данных срабатывает подписка на событие ПроверитьЗаписиДанныхФизическихЛицПередЗаписью.

Внутри этой подписки зашит код, который принудительно нормализует нумерацию записей. Давайте посмотрим на фрагмент этого кода:


Процедура ПроверитьЗаписиДанныхФизическихЛицПередЗаписью(Источник, Отказ, Замещение) Экспорт
    Если ЗарплатаКадры.ОтключитьБизнесЛогикуПриЗаписи(Источник) Тогда 
        Возврат; 
    КонецЕсли;
    
    НомерПоПорядку = 1;
    Для каждого Запись Из Источник Цикл
        Запись.НомерПоПорядку = НомерПоПорядку;
        НомерПоПорядку = НомерПоПорядку + 1;
    КонецЦикла;
КонецПроцедуры

Проблема заключается в том, что МенеджерЗаписи при сохранении передает в подписку набор, состоящий всего из одной записи. Цикл в подписке отрабатывает один раз и жестко присваивает полю НомерПоПорядку значение 1. В итоге получается конфликт: менеджер записи ожидает сохранить строку с номером 2 (согласно своему отбору), но код подписки изменил этот номер на 1 прямо в памяти перед записью. Платформа видит, что данные в объекте больше не соответствуют установленному фильтру, и блокирует операцию.

Решение №1: Переход на использование Набора Записей

Использование объекта НаборЗаписей — это наиболее корректный путь. Поскольку подписка на событие ожидает получить коллекцию записей, нам нужно предоставить ей весь пакет данных по конкретному сотруднику сразу. В этом случае счетчик НомерПоПорядку внутри подписки отработает корректно для всех строк набора.

Рассмотрим пример кода для добавления нескольких записей:


// Создаем набор записей
НаборЗаписей = РегистрыСведений.ТрудоваяДеятельностьФизическихЛиц.СоздатьНаборЗаписей();

// Устанавливаем отбор только по физическому лицу
НаборЗаписей.Отбор.ФизическоеЛицо.Установить(СсылкаНаФизЛицо);

// Если нужно добавить к существующим, сначала прочитаем их
НаборЗаписей.Прочитать();

// Добавляем новую запись
НоваяСтрока = НаборЗаписей.Добавить();
НоваяСтрока.ФизическоеЛицо = СсылкаНаФизЛицо;
НоваяСтрока.НомерПоПорядку = НаборЗаписей.Количество(); // Номер будет пересчитан подпиской, но лучше указать верный
НоваяСтрока.НаименованиеОрганизации = "ООО ТехноПром";
// ... заполнение остальных реквизитов

// Записываем весь набор
НаборЗаписей.Записать();

При таком подходе подписка увидит все записи сотрудника, пронумерует их по порядку (1, 2, 3...), и так как отбор в наборе установлен только по ФизическоеЛицо, никакого конфликта с полем НомерПоПорядку не возникнет.

Решение №2: Использование Дополнительных Свойств для обхода проверок

Иногда при миграции данных из внешних систем нам критически важно сохранить именно те номера записей, которые были в источнике, не позволяя системе ЗУП их пересчитывать. Для этого разработчики предусмотрели специальный «флаг» в дополнительных свойствах объекта.

Проанализируем условие в подписке: система проверяет свойство НеПроверятьЗаписиДанныхФизическихЛиц. Если мы установим его в значение Истина, бизнес-логика пересчета будет проигнорирована. Рассмотрим, как это реализовать программно:


НаборЗаписей = РегистрыСведений.ТрудоваяДеятельностьФизическихЛиц.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.ФизическоеЛицо.Установить(СсылкаНаФизЛицо);

// Добавляем записи с произвольными номерами
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.ФизическоеЛицо = СсылкаНаФизЛицо;
НоваяЗапись.НомерПоПорядку = 10; // Например, нам нужен именно такой номер

// Устанавливаем магическое свойство
НаборЗаписей.ДополнительныеСвойства.Вставить("НеПроверятьЗаписиДанныхФизическихЛиц", Истина);

// Теперь запись пройдет без ошибки и без изменения номера
НаборЗаписей.Записать();

Важный нюанс: Установка стандартного флага ОбменДанными.Загрузка = Истина не всегда помогает в данном регистре. Типовая логика ЗУП часто использует функцию ЗарплатаКадры.ОтключитьБизнесЛогикуПриЗаписи, которая может иметь более сложные условия проверки, чем просто режим загрузки. Поэтому использование ДополнительныеСвойства является более надежным методом.

Особенности при работе с Конвертацией Данных (КД)

Если вы выполняете перенос данных через правила обмена (КД 2.0 или 3.0), стандартный механизм часто пытается использовать МенеджерЗаписи для каждой строки регистра. Это неизбежно приведет к описанной выше ошибке.

Чтобы успешно перенести данные через КД, рекомендуем придерживаться следующих правил:

  1. В правилах конвертации объектов (ПКО) для данного регистра в обработчике «Перед загрузкой» попробуйте установить РежимЗаписи = "Загрузка".
  2. Если это не помогает, используйте алгоритм загрузки в коллекцию, а в обработчике «После загрузки данных» (в целом для конвертации) производите запись через НаборЗаписей, как было рассмотрено в Решении №2.
  3. Обязательно передавайте параметр НеПроверятьЗаписиДанныхФизическихЛиц через входящие данные или устанавливайте его непосредственно в коде обработчика загрузки.

Резюме

Подведем итоги нашего анализа. Ошибка соответствия отбору в регистре ТрудоваяДеятельностьФизическихЛиц — это следствие работы защитной бизнес-логики, которая следит за непрерывностью нумерации строк. Для обхода этой ошибки мы рекомендуем всегда использовать Набор Записей с фильтром по физическому лицу и, при необходимости, подавлять проверку через Дополнительные свойства объекта.

← На главную