При разработке в среде 1С:Предприятие 8, особенно в таких сложных конфигурациях, как ERP, КА 2 или УТ 11, программисты часто сталкиваются с ситуацией: документ создается программно, заполняется и записывается, но поле Номер остается пустым. При этом, если создавать тот же самый документ вручную через интерфейс, номер присваивается корректно и без задержек. Давайте подробно разберем, почему это происходит, как на этот процесс влияет логика платформы и как правильно организовать программную запись документа, чтобы нумерация работала корректно.
Первым делом проанализируем код, который часто становится источником проблемы. В типовых решениях для массового создания или переноса данных часто используется следующая конструкция:
НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
// Заполнение реквизитов...
НовыйДокумент.ОбменДанными.Загрузка = Истина;
НовыйДокумент.Записать();
Ключевым моментом здесь является установка свойства ОбменДанными.Загрузка в значение Истина. Рассмотрим подробнее, что происходит "под капотом" платформы в этот момент. Данный флаг предназначен для механизмов обмена данными, когда информация переносится из одной информационной базы в другую. Предполагается, что данные в источнике уже прошли все проверки, имеют уникальные идентификаторы и готовые номера.
Когда этот флаг активен, платформа и прикладной код конфигурации отключают следующие механизмы:
ПроверкаЗаполнения).ПередЗаписью, ПриЗаписи), которые содержат проверку этого флага.Как мы видим из обсуждения на форуме, в конфигурациях на базе БСП (Библиотека стандартных подсистем) существуют подписки на события, которые принудительно прерывают стандартную обработку установки номера, если установлен флаг Загрузка = Истина. Это делается для обеспечения целостности данных при обмене: если в одной базе документ имел номер "001", он должен остаться "001" и в другой, а не получить новый номер "002" по счетчику текущей базы.
Если ваша задача — просто создать новый документ в текущей базе (например, на основании какого-то действия пользователя или регламентного задания) и вы хотите, чтобы система вела себя "как при ручном вводе", самый простой и правильный путь — не устанавливать флаг Загрузка = Истина. Рассмотрим пример правильной записи:
НовыйДокумент = Документы.ПриобретениеТоваровУслуг.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Организация = Справочники.Организации.НайтиПоРеквизиту("ИНН", "7700000000");
// Заполнение остальных обязательных полей
// Флаг Загрузка НЕ устанавливаем
НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);
В этом случае при вызове метода Записать() платформа автоматически сгенерирует новый номер, учитывая периодичность нумерации и префиксы, установленные в системе.
Бывают ситуации, когда использование режима ОбменДанными.Загрузка = Истина необходимо (например, для обхода жестких проверок или при написании сложного переноса), но номер всё же должен быть назначен автоматически. В таком случае мы должны программно инициировать механизм нумерации. Разберем, как это сделать с помощью метода УстановитьНовыйНомер().
Посмотрим на пример кода:
НовыйДокумент = Документы.ЗаказКлиента.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.ОбменДанными.Загрузка = Истина;
// Вызываем генерацию номера ПЕРЕД записью
НовыйДокумент.УстановитьНовыйНомер();
НовыйДокумент.Записать();
Важно помнить, что метод УстановитьНовыйНомер() чувствителен к префиксам. Если в вашей конфигурации (например, ERP) используется префиксация по организациям или подразделениям, платформа может не знать, какой префикс использовать, если не передать его явно или не заполнить соответствующие реквизиты объекта до вызова метода. В современных конфигурациях рекомендуется передавать префикс, который можно получить через механизмы БСП.
Проанализируем ситуацию в ERP подробнее. В этой конфигурации префиксация работает через подписку на событие ПриУстановкеНовогоНомера. Если мы взглянем на код типовых модулей, мы увидим примерно следующую логику:
Процедура ПриУстановкеНовогоНомера(Источник, СтандартнаяОбработка, Префикс)
Если Источник.ОбменДанными.Загрузка Тогда
Возврат; // Выход из процедуры, номер не назначается
КонецЕсли;
// Логика формирования префикса организации...
КонецПроцедуры
Поэтому, если вы используете Загрузка = Истина, даже явный вызов УстановитьНовыйНомер() может вернуть номер без нужного вам префикса (например, просто "000000001" вместо "МС-00000001"). Чтобы этого избежать, выясним, как правильно передать префикс:
Объект.УстановитьНовыйНомер(ПрефиксДляДокумента);При программной работе с документами следует учитывать еще несколько критических моментов:
1. Очистка номера. Метод УстановитьНовыйНомер() сработает только в том случае, если текущее значение реквизита Номер является пустым (для строковых номеров — пустая строка). Если вы случайно записали туда пробел или любой другой символ, автоматическая генерация может не сработать или выдать ошибку.
2. Порядок вызова. Всегда вызывайте установку номера после заполнения даты и организации, но до вызова метода Записать(). Дата определяет период нумерации (год, месяц и т.д.), а организация — префикс. Если дата документа будет пустой, номер может быть сформирован некорректно относительно текущего года.
3. Проведение документа. Помните, что запись с флагом Загрузка = Истина создает документ в базе, но не делает его проведенным в понимании бизнес-логики (не формирует записи в регистрах накопления и бухгалтерии), даже если вы укажете РежимЗаписиДокумента.Проведение. В режиме загрузки обработчик ОбработкаПроведения просто игнорируется платформой.
Таким образом, мы выяснили причину проблемы: использование флага ОбменДанными.Загрузка = Истина блокирует стандартную работу механизмов автонумерации. Для решения задачи либо откажитесь от использования этого флага, либо вызывайте метод УстановитьНовыйНомер() вручную, предварительно подготовив необходимые префиксы.