При переносе данных между информационными базами 1С:Предприятия 7.7 часто возникает задача разделения логики нумерации документов: для определенных контрагентов или складов требуется сохранить исходный номер из файла выгрузки, а для остальных — автоматически сгенерировать новый порядковый номер с префиксом базы-приемника. Разберем, как правильно реализовать такое ветвление и избежать типичных ошибок при работе со ссылочными типами данных и автонумерацией платформы.
Типичная ошибка при попытке прописать условие вручную выглядит следующим образом:
Если Получатель = "Магазин" Тогда
ДокВН.НомерДок = НомерДок;
Иначе
ДокВН.УстановитьНовыйНомер("ЦСК");
КонецЕсли;
Выясним причину, по которой данная конструкция не срабатывает и документ всегда получает системный порядковый номер по ветке Иначе. Переменная Получатель в коде обработки заполняется путем поиска элемента в справочнике:
Если СпрМХ.НайтиПоНаименованию(СпРекв.ПолучитьЗначение(6), 0, 1) = 1 Тогда
Получатель = СпрМХ.ТекущийЭлемент();
Иначе
Получатель = "";
КонецЕсли;
В результате успешного поиска переменная Получатель содержит ссылку на объект справочника (тип данных Справочник), а в условии выполняется прямое сравнение со строковым литералом "Магазин". В платформе 1С:Предприятие 7.7 сравнение ссылки со строкой всегда возвращает Ложь, так как типы операндов не совпадают.
Рассмотрим несколько способов исправления этой ошибки в зависимости от архитектурных требований к обработке.
Если известно точное текстовое наименование получателя в структуре файла импорта, простейшим решением будет проверка значения напрямую из списка реквизитов строки файла с очисткой от пробелов через СокрЛП():
Если СокрЛП(СпРекв.ПолучитьЗначение(6)) = "Магазин" Тогда
ДокВН.НомерДок = НомерДок;
Иначе
ДокВН.УстановитьНовыйНомер("Цск");
КонецЕсли;
Этот вариант не зависит от того, был ли найден элемент в справочнике или нет, и проверяет только входящие строковые данные.
Если мы хотим проверять фактические свойства уже найденного в базе объекта, сравнивать необходимо строковое наименование элемента Получатель.Наименование, предварительно убедившись, что ссылка выбрана:
Если ПустоеЗначение(Получатель) = 0 Тогда
Если СокрЛП(Получатель.Наименование) = "Магазин" Тогда
ДокВН.НомерДок = НомерДок;
Иначе
ДокВН.УстановитьНовыйНомер("Цск");
КонецЕсли;
Иначе
ДокВН.УстановитьНовыйНомер("Цск");
КонецЕсли;
Жесткое прописывание названий объектов («хардкод») в программном коде считается плохой практикой: если пользователь базы изменит наименование склада или контрагента (например, переименует в «Магазин №1»), загрузка перестанет работать. Правильнее вынести выбор контролируемого места хранения на диалоговую форму обработки (тип данных реквизита диалога — Справочник.МестаХранения) или использовать соответствующую константу:
Если (ПустоеЗначение(Получатель) = 0) И (Получатель = ВыбПолучательДляСвоегоНомера) Тогда
ДокВН.НомерДок = НомерДок;
Иначе
ДокВН.УстановитьНовыйНомер("Цск");
КонецЕсли;
При модификации фрагмента инициализации документа критически важно соблюдать правильную последовательность установки реквизитов:
УстановитьНовыйНомер() платформы 1С 7.7 рассчитывает очередной номер строго с учетом заданной в метаданных периодичности (год, месяц, день или без периодичности) и текущего значения даты документа ДатаДок. Если вызвать УстановитьНовыйНомер() до заполнения поля даты, платформа определит номер для текущей рабочей даты системы, а не для даты из загружаемого документа. Сначала всегда заполняется ДатаДок, и лишь затем вызывается нумератор.С учетом всех правил корректный фрагмент создания и нумерации шапки документа в процедуре Загрузить() будет выглядеть следующим образом:
ДокВН.Новый();
ДокВН.ДатаДок = ДатаДок;
ДокВН.МестоХранения = МестоХранения;
ДокВН.Получатель = Получатель;
// Проверяем условие для сохранения исходного номера
Если СокрЛП(СпРекв.ПолучитьЗначение(6)) = "Магазин" Тогда
ДокВН.НомерДок = НомерДок;
Иначе
ДокВН.УстановитьНовыйНомер("Цск");
КонецЕсли;