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