В процессе эксплуатации конфигурации «Управление торговлей» (особенно в редакциях для Украины, таких как 3.2) пользователи часто сталкиваются с неприятной ситуацией: автоматическая нумерация налоговых накладных (НН) внезапно «замирает» на номере 99 или начинает выдавать ошибки при попытке записать новый документ. Несмотря на то что в конфигураторе установлена достаточная длина номера (например, 18 символов), система упорно отказывается присваивать номер 100 и выше. В этой статье мы подробно разберем причины возникновения этой проблемы и рассмотрим несколько эффективных способов её решения.
Проанализируем внутреннюю логику работы платформы «1С:Предприятие». В отличие от обычных чисел, реквизит Номер в документах является строковым. Когда система пытается сгенерировать следующий порядковый номер, она анализирует существующие записи в базе данных, сортирует их как строки и пытается инкрементировать (увеличить на единицу) числовую часть самого «большого» номера.
Выясним основную причину сбоя. Если в базе данных присутствуют номера разной фактической длины без ведущих нулей, например, Па00МрДЗ100-98 и Па00МрДЗ100-99, система видит, что после дефиса идут две цифры. При достижении значения 99 свободные разряды в этой части строки заканчиваются. Если следующий документ должен получить номер 100, то общее количество символов в номере увеличится, либо изменится структура префикса. 1С часто не может самостоятельно «раздвинуть» границы числовой части, если она не заполнена ведущими нулями до максимальной длины.
Рассмотрим ситуацию с точки зрения строковой сортировки: для компьютера строка «99» может оказаться больше строки «100», так как сравнение идет посимвольно слева направо. Чтобы избежать этой путаницы, все номера должны иметь строго одинаковую структуру и длину, заполняя пустоты нулями.
Если проблема уже возникла, первым делом необходимо привести все существующие документы в текущем периоде к единообразному виду. Рассмотрим пример кода, который поможет автоматизировать этот процесс. Мы возьмем за основу механизм обработки справочников и адаптируем его под документы НалоговаяНакладная.
Нам потребуется создать небольшую внешнюю обработку и выполнить в ней следующий алгоритм:
// Определим метаданные нашего документа
МетаданныеДокумента = Метаданные.Документы.НалоговаяНакладная;
ДлинаНомера = МетаданныеДокумента.ДлинаНомера;
// Подготовим строку из нулей для форматирования
ВсеНули = "";
Для Ид = 1 по ДлинаНомера Цикл
ВсеНули = ВсеНули + "0";
КонецЦикла;
// Формируем строку маски для метода Формат()
ФорматнаяСтрока = СтрШаблон("ЧЦ=%1; ЧН=%2; ЧВН=; ЧГ=0", ДлинаНомера, ВсеНули);
// Выбираем документы за текущий период (например, за год)
Выборка = Документы.НалоговаяНакладная.Выбрать(НачалоГода(ТекущаяДата()), КонецГода(ТекущаяДата()));
Пока Выборка.Следующий() Цикл
ОбъектДок = Выборка.ПолучитьОбъект();
// Включаем режим загрузки, чтобы не срабатывали лишние проверки в модулях
ОбъектДок.ОбменДанными.Загрузка = Истина;
// Выделяем числовую часть и дополняем её нулями
// Внимание: логика выделения числа зависит от наличия префикса
СтарыйНомер = ОбъектДок.Номер;
// Пример упрощенной логики, если нужно просто дополнить число нулями
// В реальности может потребоваться функция ПреобразоватьНомер()
ЧисловойНомер = Число(Прав(СтарыйНомер, 5)); // Допустим, хвост из 5 цифр
НовыйНомер = Формат(ЧисловойНомер, ФорматнаяСтрока);
Если ОбъектДок.Номер <> НовыйНомер Тогда
ОбъектДок.Номер = НовыйНомер;
ОбъектДок.Записать();
КонецЕсли;
КонецЦикла;
// Критически важный шаг — обновление кэша нумерации в памяти сервера
ОбновитьНумерациюОбъектов(Метаданные.Документы.НалоговаяНакладная);
После выполнения данного кода система «забудет» о коротких номерах типа ...-99 и увидит правильную последовательность ...-000099, что позволит ей беспрепятственно создать номер ...-000100.
Как мы выяснили из обсуждения, часто виновниками сбоя становятся сами пользователи. Они могут вручную редактировать номер (например, для удобства поиска или соответствия внешним реестрам), удаляя ведущие нули. Разберем, как программно запретить появление «неправильных» номеров.
Для этого нам необходимо внести изменения в Модуль объекта документа НалоговаяНакладная. Проанализируем использование процедуры ПередЗаписью:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Если это не загрузка данных из внешних источников
Если Не ОбменДанными.Загрузка Тогда
// Проверяем, не является ли номер слишком коротким
// Допустим, префикс занимает 12 символов, а номер должен быть 18
Если СтрДлина(СокрЛП(ЭтотОбъект.Номер)) < 18 Тогда
// Логика автоматического дополнения нулями
// Предположим, префикс у нас фиксированный: "Па00МрДЗ100-"
ПрефиксДлиной = 12;
ТекущийНомер = СокрЛП(ЭтотОбъект.Номер);
// Выделяем то, что ввел пользователь после префикса
ЧисловаяЧасть = Сред(ТекущийНомер, ПрефиксДлиной + 1);
// Дополняем числовую часть нулями до нужной длины
Пока СтрДлина(ЧисловаяЧасть) < (18 - ПрефиксДлиной) Цикл
ЧисловаяЧасть = "0" + ЧисловаяЧасть;
КонецЦикла;
// Собираем правильный номер обратно
ЭтотОбъект.Номер = Лев(ТекущийНомер, ПрефиксДлиной) + ЧисловаяЧасть;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Такой подход позволит удовлетворить требования пользователей (они смогут вводить «короткие» номера), но система при сохранении автоматически приведет их к каноническому виду 1С, сохранив работоспособность нумератора.
Если мы хотим полностью контролировать процесс генерации номера еще до момента записи, лучше использовать стандартный обработчик ПриУстановкеНовогоНомера. Это «правильное» место для внедрения кастомной логики префиксов.
Посмотрим на пример реализации:
Процедура ПриУстановкеНовогоНомера(СтандартнаяОбработка, Префикс)
// Можно переопределить префикс в зависимости от организации или подразделения
Префикс = "Па00МрДЗ100-";
// Если мы хотим, чтобы 1С заполнила остаток номера нулями автоматически,
// достаточно просто задать правильный префикс.
// Платформа сама найдет максимальный номер с таким префиксом и прибавит 1.
КонецПроцедуры
Часто бухгалтеры намеренно портят нумерацию в 1С, потому что внешние системы отчетности (например, M.E.Doc) не принимают номера с длинными префиксами или ведущими нулями. Выясним, как решить эту дилемму без вреда для базы данных.
Вместо изменения номера в самой 1С, следует модифицировать обработку выгрузки. В коде формирования XML-файла для налоговой накладной обычно используется функция, отвечающая за заполнение тега <R03G10S> (номер документа). В этой функции следует прописать очистку номера от префиксов:
СокрЛП() для удаления лишних пробелов.Таким образом, в 1С у вас останется технически корректный номер Па00МрДЗ100-000123, а в налоговую уйдет юридически верный номер 123.
Подводя итог, проанализируем план действий для системного администратора или программиста 1С при возникновении подобных ошибок:
ОбновитьНумерациюОбъектов() для типа документа НалоговаяНакладная. Иногда это решает проблему «зависшего» в памяти номера без изменения данных.Формат() с параметром ЧВН (через ведущие нули), чтобы исключить появление «коротких» строк.Помните, что порядок в нумерации — это залог стабильной работы распределенных баз данных и механизмов обмена. Своевременная программная проверка длины номера при вводе сэкономит массу времени при закрытии отчетного периода.