Каждый специалист, сопровождающий программные продукты на платформе 1С, рано или поздно сталкивается с ситуацией, когда пользователи нарушают стройную систему автоматической нумерации документов. Типичный сценарий: бухгалтеру или менеджеру срочно потребовалось ввести документ «задним числом» между уже существующими номерами (например, между 41 и 42). Вместо того чтобы использовать стандартные механизмы или проконсультироваться со специалистом, пользователь решает проблему «в лоб» — вручную указывает номер вида РРТУ-00041\1.
После этого автоматическая генерация номеров для новых документов ломается. Система начинает настойчиво предлагать номера РРТУ-00041\2, РРТУ-00041\3, РРТУ-00041\4 и так далее, полностью игнорируя тот факт, что в базе уже давно существуют документы с номерами 42, 43, 44 и более поздними. Даже попытка исправить дробные номера обратно на стандартные и вызов встроенного метода платформы ОбновитьНумерациюОбъектов() зачастую не приносят желаемого результата.
В этой статье мы детально проанализируем, почему платформа 1С так реагирует на появление спецсимволов в номерах, выясним скрытые причины «залипания» неверных номеров и разберем по шагам несколько эффективных способов решения этой проблемы.
Для того чтобы понять суть проблемы, проанализируем алгоритм работы механизма автонумерации платформы «1С:Предприятие». При создании нового документа система пытается автоматически сгенерировать уникальный номер. Для этого она выполняет следующие действия:
Когда в базе появляется номер РРТУ-00041\1, алгоритм платформы отрабатывает следующим образом: двигаясь справа налево, система видит крайнюю правую цифру 1. Символ обратного слэша (\) воспринимается платформой как нецифровой символ, то есть как часть префикса. Таким образом, система считает, что префикс документа — это строка РРТУ-00041\, а числовой номер документа — это 1. При создании следующего документа система берет этот «префикс», увеличивает числовую часть на единицу и выдает номер РРТУ-00041\2.
Ситуация усугубляется особенностями сортировки строковых данных в системах управления базами данных (СУБД), таких как MS SQL Server или PostgreSQL. С точки зрения СУБД, символ слэша в строке при сортировке по возрастанию может позиционироваться так, что строка с дробью признается базой данных «большей», чем чисто числовые номера (например, строка РРТУ-00041\4 может сортироваться после номера РРТУ-0000055). В результате функция поиска максимального номера всегда выбирает именно документ с дробным номером в качестве отправной точки для автонумерации.
Многие разработчики справедливо пытаются использовать встроенный метод платформы ОбновитьНумерациюОбъектов(). Этот метод предназначен для принудительного обновления кэша номеров на сервере 1С. Однако на практике часто происходит так: программист исправил все видимые «кривые» номера в журнале документов, запустил метод восстановления нумерации, но при создании нового документа система все равно выдает РРТУ-00041\4. Выясним, почему так происходит:
РРТУ-00041\3, сбой продолжится.rphost). В целях оптимизации производительности сервер кэширует диапазоны свободных номеров. Обычный запуск команды обновления нумерации из сеанса пользователя не всегда может корректно сбросить этот кэш без перезапуска рабочего процесса СУБД или службы сервера 1С.Рассмотрим комплексный подход к решению проблемы, состоящий из нескольких последовательных шагов.
Прежде всего нам необходимо убедиться, что в базе данных не осталось ни одного документа с проблемным номером, включая скрытые и помеченные на удаление объекты. Для этого напишем и выполним простой запрос в консоли запросов. Это позволит нам гарантированно выявить все проблемные места.
Проанализируем следующий текст запроса:
ВЫБРАТЬ
Реализация.Ссылка КАК ДокументСсылка,
Реализация.Номер КАК НомерДокумента,
Реализация.Дата КАК ДатаДокумента,
Реализация.ПометкаУдаления КАК Удален
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Номер ПОДОБНО "%\%"
ИЛИ Реализация.Номер ПОДОБНО "%/%"
ИЛИ Реализация.Номер ПОДОБНО "%-%"
Выполнив этот запрос, мы получим полный список документов, содержащих в номере слэши или дефисы. Нам необходимо открыть каждый найденный документ и исправить его номер вручную или полностью удалить его непосредственно из базы данных, если этот документ помечен на удаление и более не нужен.
При ручном редактировании номеров пользователи часто сокращают их длину, убирая лидирующие нули. Например, вместо стандартного номера РРТУ-0000041 (длиной 11 символов) записывают РРТУ-00041 (длиной 10 символов). Разберем, к чему это ведет: уменьшение длины номера сбивает механизм позиционирования платформы, и система перестает корректно увеличивать числовую часть.
Обязательно проследите, чтобы все исправленные номера строго соответствовали стандартной длине, заданной для данного типа документа в конфигураторе. Все пропущенные символы необходимо заполнить лидирующими нулями.
Если бизнес-требования компании и требования бухгалтерии категорически запрещают изменять уже существующие дробные номера (например, документы уже распечатаны, подписаны контрагентами и сданы в контролирующие органы), необходимо перенаправить логику автонумерации.
Как мы уже выяснили, автонумерация корректно работает только с префиксами, но совершенно не поддерживает суффиксы. Посмотрим на пример решения: вместо использования дробного суффикса в конце номера (РРТУ-00041\1) мы можем использовать дополнительный уникальный префикс в начале или середине номера. Переименуем проблемные документы в формат РРТУ-1-00041 или РРТ1-0000041.
В таком случае символ дефиса или дополнительная цифра будут находиться в левой части номера, которую платформа 1С считает префиксом. Правая часть номера останется чисто числовой и стандартной длины, что позволит автонумерации функционировать без сбоев.
После того как все номера в базе данных приведены в порядок, нам необходимо заставить сервер приложений 1С забыть старый «залипший» шаблон нумерации. Выполним следующие действия:
МетаданныеДокумента = Метаданные.Документы.РеализацияТоваровУслуг;
ОбновитьНумерациюОбъектов(МетаданныеДокумента);
Если информационная база работает в файловом режиме, этого действия будет вполне достаточно. Однако в клиент-серверном варианте кэш сервера может устоять. Для гарантированного сброса кэша выполним одно из следующих действий:
1C:Enterprise 8.3 Server Agent через консоль администрирования служб Windows или демон srv1cv83 в Linux). Это очистит оперативную память рабочих процессов rphost.Рассмотрим еще один полезный практический прием. Если в базе данных присутствует слишком много дробных документов за прошлые периоды, которые технически невозможно или крайне трудоемко переименовать, мы можем принудительно «перешагнуть» через проблемный диапазон номеров.
Допустим, максимальный проблемный номер в базе имеет вид РРТУ-00041\4. Выполним следующие действия по шагам:
РРТУ-0000100.ОбновитьНумерациюОбъектов().Платформа просканирует базу данных, обнаружит новый максимальный номер РРТУ-0000100, который по правилам сортировки СУБД окажется гарантированно больше, чем все дробные номера вида РРТУ-00041\.... Начиная с этого момента, автонумерация успешно продолжит свою работу, и следующий созданный документ автоматически получит корректный номер РРТУ-0000101. Ошибочный диапазон останется в прошлом, а новые документы будут создаваться без сбоев и ручного вмешательства.