В процессе работы с конфигурациями на платформе «1С:Предприятие» (например, в «1С:Зарплата и Управление Персоналом 2.5») пользователи и разработчики часто сталкиваются с ошибкой проведения документов, которая сопровождается системным сообщением: «Запись с такими ключевыми полями существует!». Особенно часто эта проблема проявляется при проведении документов, которые делают движения по кастомным (доработанным) регистрам сведений, например, по регистру СТ_ИнструкцииДолжности, связанному с изменением штатного расписания.
В этой статье мы подробно проанализируем ситуацию, выясним причины возникновения данной ошибки на уровне платформы «1С:Предприятие» и разберем по шагам несколько практических способов её решения — как для обычных пользователей, так и для программистов 1С.
Для того чтобы понять природу ошибки, рассмотрим подробнее, как платформа 1С работает с уникальностью данных в регистрах сведений. Каждый регистр сведений имеет набор ключевых полей, которые в совокупности образуют уникальный ключ записи. Платформа физически не может хранить в базе данных две строки с абсолютно одинаковым ключом записи.
Состав уникального ключа записи напрямую зависит от структуры и свойств регистра сведений:
Подразделение и Должность). Это означает, что в таком регистре для конкретного подразделения и конкретной должности может существовать только одна-единственная запись. Любая попытка записать вторую строку с аналогичной комбинацией вызовет ошибку уникальности.Период. В этом случае уникальность контролируется по комбинации Измерения + Период. Это позволяет хранить историю изменений: на разные даты (периоды) в системе могут существовать записи с одинаковым подразделением и должностью.Регистратор (ссылка на документ, сделавший движения). В таком регистре записи разных документов никогда не будут конфликтовать между собой, даже если у них совпадают все измерения, поскольку у них будут разные регистраторы. Конфликт уникальности здесь возможен только в том случае, если один и тот же документ пытается записать дублирующиеся строки внутри своего собственного набора движений.Проанализируем ситуацию из обсуждения на форуме: при проведении документа «Изменение штатного расписания организации» за 01.01.2020 возникает ошибка записи в регистр СТ_ИнструкцииДолжности. Регистр является независимым и непериодическим, а его ключевыми измерениями выступают подразделение и должность. Поскольку в регистре уже есть запись по этой должности от другого документа (более позднего или введенного вручную), проведение старого документа блокируется платформой, так как уникальный ключ записи (Подразделение + Должность) уже занят.
---
Перед тем как приступать к изменению метаданных в конфигураторе, рассмотрим самый простой и быстрый способ, который доступен обычному пользователю без привлечения программиста. Очень часто ошибка возникает из-за того, что пользователь дважды указал одну и ту же аналитику в табличной части проводимого документа.
Разберем этот процесс по шагам:
Подразделение и Должность.Если дублей внутри документа нет, но ошибка все равно возникает, это означает, что запись с такими измерениями уже существует непосредственно в самом регистре сведений (она была создана другим документом или введена вручную). Переходим к следующим вариантам решения.
---
Если бизнес-логика вашей компании предполагает, что штатное расписание и должностные инструкции могут меняться со временем, то использование непериодического регистра является грубой архитектурной ошибкой. В непериодическом регистре невозможно хранить историю изменений — там всегда будет находиться только одна актуальная запись.
Рассмотрим подробнее, как сделать регистр периодическим в конфигураторе 1С:
СТ_ИнструкцииДолжности).Важно: При изменении периодичности существующие записи в базе данных не пропадут, но у них заполнится системное поле Период (по умолчанию оно заполнится пустой датой «01.01.0001» или текущей датой в зависимости от способа обновления). После этого проведение старых документов за разные даты перестанет вызывать конфликты, так как уникальность будет определяться связкой «Период + Подразделение + Должность».
---
Если вы являетесь разработчиком и хотите гарантировать, что при проведении документа в регистр сведений никогда не попытаются записаться дублирующиеся строки из табличной части, вам необходимо доработать программный код в модуле проведения документа.
Посмотрим на пример кода, который решает эту задачу с помощью предварительной группировки (сворачивания) таблицы значений перед ее записью в регистр сведений:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// 1. Инициализируем набор записей нашего независимого регистра
НаборЗаписей = РегистрыСведений.СТ_ИнструкцииДолжности.СоздатьНаборЗаписей();
// 2. Выгружаем данные из табличной части документа в таблицу значений
ТаблицаДвижений = ТабличнаяЧастьШтатноеРасписание.Выгрузить();
// 3. Сворачиваем таблицу по ключевым измерениям регистра,
// чтобы исключить возникновение дублей в рамках одной транзакции
ТаблицаДвижений.Свернуть("Подразделение, Должность", "КоличествоСтавок");
// 4. Заполняем набор записей сгруппированными данными
Для Каждого СтрокаДанных Из ТаблицаДвижений Цикл
НоваяЗапись = НаборЗаписей.Добавить();
ЗаполнитьЗначенияСвойств(НоваяЗапись, СтрокаДанных);
// Если регистр периодический, не забываем указать период (дату документа)
// НоваяЗапись.Период = Дата;
КонецЦикла;
// 5. Записываем набор в базу данных с замещением старых движений документа
НаборЗаписей.Записать(Истина);
КонецПроцедуры
Использование метода Свернуть() позволяет гарантированно избежать дублей внутри одной транзакции проведения, объединяя совпадающие строки и суммируя их ресурсы.
---
Если регистр сведений независимый, и при проведении нового документа система должна просто перезаписывать (обновлять) старые данные по этой должности и подразделению, необходимо использовать режим записи с замещением.
Проанализируем ситуацию: если мы программно создаем менеджер записи или набор записей, по умолчанию метод Записать() может пытаться добавить новую запись поверх существующей, что приведет к ошибке уникальности ключа. Чтобы этого избежать, необходимо явно использовать параметр Замещать = Истина.
Рассмотрим пример программной записи одной строки через менеджер записи:
МенеджерЗаписи = РегистрыСведений.СТ_ИнструкцииДолжности.СоздатьМенеджерЗаписи();
// Заполняем ключевые поля (измерения)
МенеджерЗаписи.Подразделение = ВыбранноеПодразделение;
МенеджерЗаписи.Должность = ВыбраннаяДолжность;
// Заполняем ресурсы и реквизиты
МенеджерЗаписи.Инструкция = СсылкаНаИнструкцию;
// Записываем с обязательным замещением существующей записи в базе данных
МенеджерЗаписи.Записать(Истина);
При использовании параметра Истина в методе Записать() платформа сначала выполнит поиск существующей записи по указанным измерениям в базе данных. Если такая запись будет найдена, платформа перезапишет её новые ресурсы, не выдавая ошибку уникальности ключевых полей.
---
Если логика работы вашей конфигурации требует, чтобы записи в регистре СТ_ИнструкцииДолжности жестко соответствовали документам проведения (то есть каждый документ создавал свои собственные движения, которые должны автоматически очищаться при отмене проведения документа), лучшим архитектурным решением будет изменение режима записи регистра сведений.
Выполним следующие шаги в конфигураторе:
СТ_ИнструкцииДолжности.После применения этих изменений платформа 1С возьмет под полный контроль уникальность записей в разрезе документов-регистраторов. Ошибка «Запись с такими ключевыми полями существует» больше не побеспокоит пользователей при проведении разных документов, так как каждый документ будет отвечать только за свой собственный набор записей.