При работе в крупных конфигурациях на базе платформы 1С:Предприятие 8.3, таких как 1С:ERP Управление предприятием или 1С:Зарплата и управление персоналом, технические специалисты часто сталкиваются с ошибкой: «Запись с такими ключевыми полями существует!». Особенно часто это происходит в момент заполнения или расчета документа Начисление зарплаты и взносов. Ошибка локализуется в общем модуле УчетРабочегоВремени при попытке записи данных в регистр сведений Графики работы по видам времени.
В этой статье мы подробно разберем, почему возникает эта «мистическая» ошибка, как правильно диагностировать содержимое наборов записей и какие неочевидные причины могут приводить к конфликту ключей в регистре.
Часто программисты пытаются найти проблему, просто сделав запрос к регистру сведений Графики работы по видам времени по «проблемному» сотруднику и периоду. Однако стандартный запрос может показать, что записей в базе нет. Рассмотрим ситуацию подробнее.
Ошибка обычно возникает в процедуре ЗаполнитьОчереднойНабор() при выполнении метода Набор.Записать(Ложь). Параметр Ложь (или его отсутствие по умолчанию в некоторых контекстах) указывает системе, что записи нужно не замещать, а добавлять. Если в коллекции Набор, которая подготовлена в оперативной памяти, уже присутствуют две абсолютно одинаковые строки (по измерениям), то при попытке записи 1С выдаст ошибку дублирования.
Важный момент: проблема заключается не в том, что в базе данных уже есть такая запись, а в том, что алгоритм формирования данных внутри конфигурации по какой-то причине создал две идентичные строки для одного и того же сотрудника, на одну и ту же дату и вид времени в рамках одного набора.
Для того чтобы убедиться в наличии дублей внутри самого формируемого объекта НаборЗаписей, мы рекомендуем использовать метод выгрузки в таблицу значений и последующего сравнения количества строк. Рассмотрим пример кода, который можно вставить в точку останова или временно добавить в модуль перед вызовом Набор.Записать():
// Выгружаем текущий набор записей в таблицу значений
ТаблицаПроверки = Набор.Выгрузить();
// Сохраняем исходное количество строк
КоличествоДо = ТаблицаПроверки.Количество();
// Сворачиваем таблицу по всем измерениям регистра
// Для регистра "Графики работы по видам времени" это обычно:
// ПериодРегистрации, Сотрудник, Месяц, Дата, ВидВремени и т.д.
ТаблицаПроверки.Свернуть("ПериодРегистрации, Сотрудник, Месяц, Дата, ВидВремени");
// Сравниваем количество строк
Если КоличествоДо <> ТаблицаПроверки.Количество() Тогда
Сообщить("Обнаружены дубли в наборе записей!");
// Здесь можно дополнительно проанализировать, какой именно сотрудник дублируется
КонецЕсли;
Этот простой метод позволяет мгновенно подтвердить, что ошибка генерируется из-за данных «в памяти», а не из-за конфликта с уже существующими данными в таблицах SQL-сервера.
Разберем типичную ловушку, в которую попадают разработчики. Текст ошибки 1С может быть довольно длинным и содержать значения всех измерений. В регистре Графики работы по видам времени ключевыми полями являются:
Период регистрации (обычно начало месяца начисления).Месяц (месяц, за который начисляется зарплата).Дата (конкретный календарный день).Сотрудник.Проанализируем ситуацию: если в сообщении об ошибке вы видите дату 01.06.2018 в начале и 12.06.2018 в конце, это означает, что Период регистрации — это первое число, а реальный конфликт произошел на дату 12 июня. Часто разработчики смотрят только на первую дату и ищут проблему на начало месяца, игнорируя реальный день, вызвавший сбой.
Если мы выяснили, что дубли создаются программно, нужно понять, на основании каких первичных данных система формирует эти записи. Рассмотрим основные причины возникновения дублей в 1С:ERP и ЗУП:
Индивидуальный график на один и тот же месяц. Несмотря на контроли в системе, при определенных обстоятельствах (например, после переноса данных) такие дубли могут возникнуть.Работа в выходные и праздничные дни, который назначен на день, который и так является рабочим по основному графику сотрудника. Иногда алгоритм заполнения начисления зарплаты может некорректно обрабатывать такие наложения.Явка и Ночные), система должна создавать разные записи. Но если по ошибке дважды указан один и тот же вид времени, возникнет конфликт ключей.Табель, он имеет приоритет. Попробуем перезаполнить и перепровести Табель за проблемный месяц. Ошибка в начислении часто является лишь следствием некорректно сформированных строк в табеле.В некоторых версиях 1С:ERP 2.1 и ранних 2.4 наблюдались программные ошибки, связанные с «ночными» сменами, переходящими через полночь. Проанализируем алгоритм: когда смена начинается в 22:00 одного дня и заканчивается в 06:00 следующего, система дробит время. В редких случаях из-за некорректных настроек графиков или округления времени алгоритм мог попытаться записать две строки на одну и ту же дату для одного сотрудника.
Также стоит обратить внимание на режим записи набора. Если вы дорабатываете систему самостоятельно, помните, что использование Набор.Записать(Ложь) требует идеальной чистоты данных в самом наборе. Если есть сомнения, рассмотрите возможность использования Набор.Записать(Истина), но только если вы уверены, что полное замещение данных по этому отбору (обычно по сотруднику и периоду) допустимо и не удалит лишнего.
Подведем итоги. Если вы столкнулись с «мистикой» в графиках работы, выполните следующие действия:
График работы, Индивидуальный график и Табель по конкретному сотруднику.Таким образом, большинство проблем с дублированием записей в регистре Графики работы по видам времени решается тщательным анализом формируемого набора данных в отладчике и проверкой первичных кадровых документов сотрудника.