Почему при переносе даты документа на прошлый год возникает ошибка неуникальности номера и как её исправить?

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

При работе с документами в 1С:Предприятие разработчики и пользователи нередко сталкиваются с ситуацией: если создать новый документ задним числом (в предыдущем году), платформа корректно генерирует для него новый порядковый номер. Однако если открыть уже ранее записанный документ текущего года и изменить его дату на прошлый год, при попытке записи возникает ошибка: «Значение поля "Номер" не уникально».

Проанализируем механику работы платформы 1С, выясним причину такого поведения и разберем варианты программного решения проблемы.

Особенности механизма автонумерации платформы 1С

Разберем по шагам, почему платформа ведет себя именно так:

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

Если в конфигурации один вид документа при смене года перенумеровывается штатно, а его копия — выдает ошибку, причина чаще всего кроется в том, что скопированный объект метаданных не был добавлен в соответствующую подписку на событие (например, ПередЗаписью) или определяемый тип, отвечающий за контроль периодичности нумерации.

Способ 1. Проверка смены периода в событии ПередЗаписью

Рассмотрим основной способ решения задачи на уровне сервера. Создадим или дополним обработчик события ПередЗаписью (в модуле объекта документа или через общую подписку на события). Основная идея заключается в том, чтобы сравнить сохраненную в базе дату документа с новой датой. Если изменился расчетный период нумерации, мы сбрасываем номер или принудительно назначаем новый.

Посмотрим на пример реализации логики для модуля объекта документа:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
	
	// Проверяем только для ранее записанных документов
	Если Не ЭтоНовый() Тогда
		// Получаем исходную дату документа из информационной базы
		ДатаВБазе = Ссылка.Дата;
		
		// Проверяем, изменился ли год документа
		Если НачалоГода(Дата) <> НачалоГода(ДатаВБазе) Тогда
			// Очищаем номер, чтобы платформа автоматически назначила новый для целевого года
			Номер = "";
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

Если в системе используется префиксация номеров (например, префикс информационной базы или организации), вместо простой очистки номера вызовем метод УстановитьНовыйНомер() с передачей нужного префикса.

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

Рассмотрим вариант, когда необходимо контролировать номер документа непосредственно в интерактивном режиме при редактировании реквизита Дата пользователем. Посмотрим на алгоритм контроля периода смены номера в зависимости от настроек метаданных:


// Обработчик события изменения даты на форме документа
Процедура ДатаПриИзменении(Элемент)
	ПроверитьНомерДокумента(ЭтотОбъект, мТекущаяДатаДокумента);
КонецПроцедуры

// Процедура сверки периода и переустановки номера
Процедура ПроверитьНомерДокумента(ДокументОбъект, НачальнаяДатаДокумента) Экспорт
	
	ПериодСменыНомера = ДокументОбъект.Метаданные.ПериодичностьНомера;
	РазностьДат = 0;
	
	Если ПериодСменыНомера = Метаданные.СвойстваОбъектов.ПериодичностьНомераДокумента.Год Тогда
		РазностьДат = НачалоГода(НачальнаяДатаДокумента) - НачалоГода(ДокументОбъект.Дата);
	ИначеЕсли ПериодСменыНомера = Метаданные.СвойстваОбъектов.ПериодичностьНомераДокумента.Квартал Тогда
		РазностьДат = НачалоКвартала(НачальнаяДатаДокумента) - НачалоКвартала(ДокументОбъект.Дата);
	ИначеЕсли ПериодСменыНомера = Метаданные.СвойстваОбъектов.ПериодичностьНомераДокумента.Месяц Тогда
		РазностьДат = НачалоМесяца(НачальнаяДатаДокумента) - НачалоМесяца(ДокументОбъект.Дата);
	ИначеЕсли ПериодСменыНомера = Метаданные.СвойстваОбъектов.ПериодичностьНомераДокумента.День Тогда
		РазностьДат = НачальнаяДатаДокумента - ДокументОбъект.Дата;
	КонецЕсли;
	
	Если РазностьДат <> 0 Тогда
		УстановитьНомерДокумента(ДокументОбъект);
	КонецЕсли;
	
КонецПроцедуры

// Процедура непосредственной установки номера с учетом реквизитов
Процедура УстановитьНомерДокумента(ДокументОбъект) Экспорт
	
	ПрефиксНомера = "";
	МетаданныеДокумента = ДокументОбъект.Метаданные;
	
	// Если у документа есть реквизит Организация, учитываем ее префикс
	Если МетаданныеДокумента.Реквизиты.Найти("Организация") <> Неопределено Тогда
		Если ЗначениеЗаполнено(ДокументОбъект.Организация) И ЗначениеЗаполнено(ДокументОбъект.Организация.Префикс) Тогда
			ПрефиксНомера = ДокументОбъект.Организация.Префикс;
		КонецЕсли;
	КонецЕсли;
	
	ДокументОбъект.УстановитьНовыйНомер(ПрефиксНомера);
	
КонецПроцедуры

Способ 3. Использование подписок на события и БСП

Если в конфигурации используется Библиотека стандартных подсистем (БСП) или собственные централизованные подписки на события:

  1. Откроем дерево метаданных в конфигураторе и перейдем в ветку Общие → Подписки на события.
  2. Найдем подписки, обрабатывающие события ПередЗаписью и ПриУстановкеНовогоНомера для документов (например, подписку по контролю нумерации и автопрефиксации).
  3. Откроем свойство Источник нужной подписки и убедимся, что созданный или скопированный документ отмечен в списке типов.
  4. Если конфигурация использует определяемые типы для документов с автонумерацией, добавим новый вид документа в соответствующий ОпределяемыйТип.

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

← На главную