В процессе разработки конфигураций и написания внешних обработок для платформы 1С Предприятие 8.3 часто возникает необходимость программно отличить только что созданный объект от уже существующего в базе данных. Это критически важно для корректной работы алгоритмов обмена данными, автоматического заполнения полей при создании и предотвращения дублирования записей. Ошибка в определении статуса документа может привести к некорректному поведению системы или потере данных при сохранении.
Существует несколько надежных способов проверить, является ли объект новой записью. Выбор конкретного метода зависит от контекста задачи: пишете ли вы код внутри модуля объекта, в общей форме или во внешней обработке. Понимание механики работы платформы с идентификаторами ссылок и флагами состояния позволяет избежать типичных ошибок при программировании.
В данной статье мы подробно разберем основные свойства и методы, которые позволяют точно установить факт новизны документа. Мы рассмотрим как стандартные свойства встроенного языка, так и специфические нюансы работы с проведением и помечанием на удаление, чтобы вы могли выбрать оптимальный вариант для вашего случая.
Анализ свойства Ссылка и пустого идентификатора
Самым фундаментальным способом определить новый объект является проверка его свойства Ссылка. В момент создания экземпляра документа в памяти, до момента его первой записи в базу данных, ссылка на этот объект считается пустой. Пустая ссылка имеет уникальный внутренний идентификатор, который отличается от любого реального GUID, присвоенного записанному элементу.
Для проверки пустоты ссылки в языке запросов и встроенном языке 1С используется специальная конструкция. Вы можете сравнить ссылку с предопределенным значением Ссылка.ПустаяСсылка() или использовать функцию ПустаяСсылка(). Если условие истинно, значит, объект еще ни разу не был сохранен в информационную базу и является новым.
Этот метод универсален и работает для всех типов ссылочных объектов: документов, справочников, планов счетов и регистров. Однако Поэтому проверка должна выполняться строго до вызова метода Записать().
⚠️ Внимание: В некоторых редких случаях при работе с внешними источниками данных или сложными механизмами обмена свойство ссылки может быть инициализировано заранее. Всегда проверяйте контекст создания объекта перед использованием этого метода.
Рассмотрим пример кода, демонстрирующий правильную проверку:
Если ДокументОбъект.Ссылка = Ссылка.ПустаяСсылка() Тогда
Сообщить("Это новый документ, еще не записанный в базу");
Иначе
Сообщить("Документ уже существует в базе данных");
КонецЕсли;
Используйте проверку на пустую ссылку как основной метод в модулях форм и внешних обработках, где объект еще не записан.
Использование метода УстановленНовый
Более современным и предпочтительным способом, введенным в последних версиях платформы 1С 8.3, является использование метода УстановленНовый(). Этот метод явно возвращает булево значение, указывающее на то, был ли объект создан заново в текущей сессии работы с данными. Он инкапсулирует логику проверки внутренней ссылки, делая код более читаемым и понятным.
Метод УстановленНовый() возвращает Истина, если объект был создан конструктором СоздатьДокумент() или аналогичным методом и еще не был записан. После вызова метода Записать() этот флаг автоматически сбрасывается в Ложь. Это избавляет разработчика от необходимости вручную сравнивать ссылки с пустыми значениями.
Особенность данного подхода заключается в его явности. Читая код, любой разработчик сразу понимает намерение автора, не вникая в детали реализации сравнения ссылок. Кроме того, метод корректно обрабатывает ситуации копирования объектов, где логика может отличаться от простого создания.
- 🔹 Метод возвращает
Истинасразу после создания объекта. - 🔹 Флаг автоматически сбрасывается после успешной записи в базу.
- 🔹 Работает корректно при копировании существующих документов.
- 🔹 Улучшает читаемость кода по сравнению с проверкой ссылок.
Пример использования метода в процедуре обработки перед записью:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если УстановленНовый() Тогда
// Логика инициализации для нового документа
ЗаполнитьРеквизитыПоУмолчанию();
КонецЕсли;
КонецПроцедуры
☑️ Проверка статуса нового объекта
Особенности работы с флагом проведения
Часто возникает путаница между понятиями "новый документ" и "непроведенный документ". Важно четко разграничивать эти состояния. Документ может быть давно создан и записан в базу (то есть не являться новым по ссылке), но при этом не иметь статуса проведенного. Для проверки проведения используется свойство Проведен.
Свойство Проведен возвращает Истина, если документ имеет отметку о проведении в базе данных. Новый документ по умолчанию всегда непроведенный, но обратное утверждение неверно: непроведенный документ не обязательно является новым. Он может быть старым документом, который вернули в состояние "не проведен" или создали черновик, сохранили, а теперь редактируете.
При разработке логики бизнес-процессов часто требуется реагировать именно на событие первого проведения нового документа. В этом случае необходимо комбинировать проверку на новизну и проверку флага проведения. Это позволяет отделить создание черновика от финализации операции.
| Состояние объекта | Ссылка пустая | Проведен | Комментарий |
|---|---|---|---|
| Только создан в памяти | Да | Нет | Абсолютно новый объект |
| Записан как черновик | Нет | Нет | Существует в базе, но не проведен |
| Проведен впервые | Нет | Да | Объект существует и активен |
| Распроведен | Нет | Нет | Старый объект, снят с проведения |
Использование комбинации проверок позволяет строить гибкие алгоритмы. Например, вы можете запретить проведение документа, если некоторые реквизиты не заполнены, но только если документ новый. Для старых документов правила могут быть мягче из-за исторических данных.
Почему важно различать новый и непроведенный документ?
Различие критично для регламентных операций. Непроведенный документ занимает место в базе и имеет номер, влияя на нумерацию, но не формирует движения по регистрам. Новый документ еще не имеет номера (до записи) и не влияет ни на что.
Проверка в модуле объекта и общих формах
Контекст выполнения кода накладывает определенные ограничения на выбор метода проверки. В модуле объекта документа (например, в событии ПриСозданииНаСервере) вы имеете прямой доступ к свойствам самого объекта. Здесь наиболее эффективно использовать метод УстановленНовый(), так как он нативно поддерживается контекстом модуля.
В отличие от модуля объекта, в общих формах или внешних обработках вы часто работаете с объектом, полученным через выборку или загруженным по ссылке. В таких случаях свойство УстановленНовый может быть недоступно или возвращать некорректное значение, если объект не был создан в текущем сеансе. Здесь надежнее всего проверять свойство Ссылка.
Если вы разрабатываете обработку, которая получает список документов для анализа, вам придется загружать каждый документ в память для проверки его статуса. Это может быть ресурсоемкой операцией. Оптимизированный подход заключается в добавлении виртуального поля в запрос, которое будет сигнализировать о дате создания, хотя это не дает 100% гарантии новизны в рамках текущей транзакции.
⚠️ Внимание: В распределенных информационных базах (РИБ) логика определения нового документа усложняется. Узел может считать документ новым, в то время как в центральном узле он уже существует. Сверяйте правила обмена для вашей конфигурации.
Для внешних скриптов и расширений, где нет прямого доступа к модулю объекта, используйте следующий паттерн:
Функция ЭтоНовыйОбъект(Объект) Экспорт
Если ТипЗнч(Объект) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
Объект = Объект.ПолучитьОбъект();
КонецЕсли;
Возврат Объект.УстановленНовый();
КонецФункции
Влияние нумерации документов на определение новизны
Нумерация документов в 1С тесно связана с процессом их записи. Обычно номер присваивается автоматически в момент записи нового документа, если не включен режим ручной нумерации. Наличие или отсутствие номера может служить косвенным признаком новизны объекта, но полагаться на него как на основной критерий опасно.
В конфигурациях с автонумерацией новый документ до момента записи имеет пустое поле Номер. После записи номер заполняется. Однако, если пользователь отменил проведение или редактирует старый документ, номер остается заполненным. Таким образом, пустой номер часто коррелирует с новым документом, но не тождественен ему.
Существуют сценарии, когда номер присваивается до записи, например, при использовании специальных механизмов резервирования номеров. В таких случаях проверка на пустоту номера даст ложноотрицательный результат. Всегда используйте проверку ссылки или метода УстановленНовый как первичный фильтр.
- 🔸 Пустой номер часто указывает на новый документ, но не гарантирует это.
- 🔸 Ручная нумерация полностью ломает логику определения по номеру.
- 🔸 Номер присваивается в момент транзакции записи, а не создания в памяти.
- 🔸 Для отчетов лучше использовать дату создания, а не номер.
Типичные ошибки при проверке статуса документа
Одной из самых распространенных ошибок является попытка проверить новизну объекта после того, как он уже был записан в базу в рамках той же сессии. Как только вызван метод Записать(), объект теряет статус "нового". Если ваша логика требует разделения действий "при создании" и "при изменении", необходимо сохранять состояние в переменную до записи.
Другая ошибка связана с копированием документов. При копировании создается новый объект, основанный на данных старого. Метод УстановленНовый() вернет Истина, что технически верно, но бизнес-логика может требовать иного отношения к таким документам (например, сохранение некоторых связей с оригиналом). В таких случаях нужно дополнительно анализировать источник данных.
Также разработчики часто забывают о транзакциях. Если проверка новизны происходит в одной транзакции, а запись в другой, состояние может измениться непредсказуемо при параллельной работе пользователей. Блокировка объекта или использование механизмов изоляции транзакций может потребоваться в высоконагруженных системах.
⚠️ Внимание: Интерфейс и поведение методов могут незначительно меняться в зависимости от версии платформы 1С и конкретной конфигурации (Бухгалтерия, УТ, ЗУП). Всегда тестируйте код на актуальной версии релиза.
Для минимизации ошибок рекомендуется выносить логику проверки в общие модули или универсальные процедуры. Это позволяет централизованно обновлять алгоритм определения новизны, если платформа внесет изменения в будущих версиях.
Самый надежный способ — комбинация метода УстановленНовый() для новых сессий и проверки Ссылка.ПустаяСсылка() для универсальных случаев.
Можно ли определить новый документ через запрос к базе данных?
Напрямую через запрос определить, является ли документ "новым" в контексте текущей сессии, нельзя, так как запрос работает с уже записанными данными. Однако можно отфильтровать документы по дате создания (если ведется регистр сведений о датах создания) или по периоду, чтобы найти недавно добавленные записи.
Что происходит со свойством УстановленНовый после отмены записи?
Если запись документа была отменена (возникла ошибка или пользователь нажал Отмена), объект остается в памяти. Свойство УстановленНовый сохранит значение Истина, так как объект так и не был успешно сохранен в базу данных. Это позволяет пользователю повторить попытку записи без потери статуса новизны.
Как проверить новый документ в обработке загрузки данных?
В обработках загрузки данных, где документы создаются пакетно, лучше всего использовать проверку Ссылка.ПустаяСсылка() перед записью каждого элемента. Метод УстановленНовый() также будет работать, но важно убедиться, что объект не был получен из выборки, а именно создан заново конструктором.
Влияет ли режим совместимости на работу метода УстановленНовый?
Да, метод УстановленНовый() появился в относительно новых версиях платформы. Если ваша конфигурация работает в режиме совместимости со старыми версиями (например, до 8.3.10), этот метод может быть недоступен. В таких случаях необходимо использовать классическую проверку через Ссылка.ПустаяСсылка().
Может ли документ быть новым и проведенным одновременно?
Технически, в момент выполнения кода в событии ПередЗаписью или ПередПроведением, документ может быть новым (еще не записан) и иметь установленный флаг проведения (который запишется вместе с документом). Поэтому проверка Проведен на новом объекте может вернуть Истина, если флаг был установлен программно или пользователем до нажатия кнопки записи.