Как исправить ошибку с субконто и значением NULL в проводках регистра бухгалтерии

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

При работе с регистром бухгалтерии разработчики и администраторы иногда сталкиваются с нестандартным состоянием данных: на счете задано несколько видов субконто (например, Контрагент, Договор, Документ расчетов), но в конкретной проводке аналитика заполнена некорректно. В физической таблице базы данных вместо штатного пустого значения хранится NULL (например, набор аналитик выглядит как Неопределено / Неопределено / NULL). Попытка отредактировать, отменить проведение или сторнировать такой документ приводит к ошибке СУБД о нарушении уникальности ключей в индексах (Cannot insert duplicate key / Попытка вставки неуникального значения в индекс).

Проанализируем природу этой проблемы, выясним, почему невозможно записать NULL средствами встроенного языка 1С, и подробно разберем рабочие способы восстановления целостности данных.

Почему возникает значение NULL в субконто и ошибка СУБД

Выясним основные причины, приводящие к такому поведению системы:

  1. Изменение состава субконто на счете задним числом. Если к уже используемому счету в плане счетов добавляется новый вид субконто, платформа не пересчитывает и не заполняет автоматически новые колонки в старых движениях. В физических таблицах СУБД поля новой аналитики остаются со значением NULL, тогда как штатным пустым значением для составных типов в 1С является Неопределено или пустая ссылка соответствующего типа.
  2. Некорректная прямая загрузка данных. При загрузках через внешние обмены или прямой программной записи наборов записей без инициализации всех разрезов аналитики поля могут остаться неинициализированными на уровне базы данных.
  3. Механизм расчета агрегатов и итогов. Ошибка СУБД о дублировании ключей возникает не из-за самой таблицы движений, а из-за агрегатных таблиц итогов регистра бухгалтерии (таблиц остатков, оборотов и субконто). При попытке изменить или распровести документ платформа рассчитывает дельту и пытается обновить итоги. Наличие физического NULL нарушает работу уникальных индексов таблиц итогов, что и провоцирует откат транзакции.

Ограничение платформы: почему нельзя записать NULL кодом 1С

В объектной модели РегистрБухгалтерииНаборЗаписей коллекция субконто строго типизирована на основании типов плана видов характеристик. Любая попытка присвоить полю значение Null:


Для Каждого Проводка Из НаборПроводок Цикл
    Проводка.СубконтоКт[ВидСубконтоДокумент] = Null;
КонецЦикла;

автоматически приводит к приведению типа к Неопределено или пустой ссылке. Создать корректирующую проводку с физическим значением NULL через встроенный язык 1С невозможно. Единственный корректный путь — восстановить штатные пустые значения в исходной проблемной записи.

Способ 1. Исправление через программное отключение и пересчет итогов

Рассмотрим наиболее надежный и быстрый способ исправления записей без выгрузки базы данных и без прямого вмешательства в SQL-таблицы. Чтобы обойти ошибку проверки уникальности индексов при перезаписи, временно отключим ведение итогов по регистру бухгалтерии.

Разберем по шагам последовательность действий:

  1. Программно отключаем использование итогов по целевому регистру бухгалтерии. При выключенных итогах платформа перестает обновлять агрегатные таблицы, и запись набора проводок проходит успешно.
  2. Считываем проблемный набор записей документа, перезаписываем его (при этом платформа сама проставит корректные значения по умолчанию для всех субконто).
  3. Включаем использование итогов обратно и выполняем их полный пересчет.

Посмотрим на пример обработки для выполнения этой процедуры:


ИмяРегистра = "Хозрасчетный";
Регистр = РегистрыБухгалтерии[ИмяРегистра];

// Шаг 1. Отключаем использование итогов
Регистр.УстановитьИспользованиеИтогов(Ложь);

// Шаг 2. Перезаписываем проблемный документ
НаборЗаписей = Регистр.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Значение = СсылкаНаПроблемныйДокумент;
НаборЗаписей.Прочитать();

// При необходимости явно инициализируем субконто или просто перезаписываем набор
Для Каждого Запись Из НаборЗаписей Цикл
    // Платформа автоматически заполнит отсутствующие субконто значениями Неопределено
КонецЦикла;

НаборЗаписей.Записать();

// Шаг 3. Включаем итоги и пересчитываем их
Регистр.УстановитьИспользованиеИтогов(Истина);
Регистр.ПересчитатьИтоги();

Способ 2. Сдвиг границы рассчитанных итогов

Если нет возможности полностью отключать итоги регистра, можно воспользоваться стандартным механизмом управления периодом итогов:

  1. Открываем стандартную обработку Управление итогами (или используем метод УстановитьПериодРассчитанныхИтогов).
  2. Устанавливаем границу рассчитанных итогов на дату, предшествующую дате проблемного документа.
  3. Открываем и успешно перезаписываем или сторнируем документ — так как итоги на эту дату не рассчитаны, коллизии в индексах СУБД не возникнет.
  4. Возвращаем границу рассчитанных итогов на текущую дату и выполняем пересчет итогов за затронутый период.

Способ 3. Восстановление через файловую информационную базу

Рассмотрим альтернативный способ, который помогает в ситуациях, когда СУБД блокирует любые операции над таблицей:

  1. Создаем резервную копию и выгружаем информационную базу в файл (.dt).
  2. Разворачиваем базу в файловом варианте работы (движок файловой базы менее чувствителен к неконсистентным индексам итогов).
  3. В файловой базе программно открываем проблемный набор записей, инициализируем третье субконто значением Неопределено и записываем движения.
  4. Выполняем полный пересчет итогов регистра через режим Тестирование и исправление информационной базы или обработку управления итогами.
  5. Выгружаем исправленную базу обратно в клиент-серверный вариант (SQL).

Поиск остальных некорректных записей в базе

Чтобы убедиться, что в информационной базе не осталось других проводок с незаполненными физическими полями субконто, выполним диагностический запрос. Для этого проверяем наличие записей, где поле субконто не заполнено (ЕСТЬ NULL), при условии, что в плане счетов для соответствующего счета эта аналитика предусмотрена.

После выявления всех подобных документов их следует пакетно перезаписать в цикле при временно отключенных итогах регистра, как показано в первом способе.

← На главную