Проблема сбитой нумерации в 1С:Зарплата и Управление Персоналом 3.1 — это классическая ситуация, с которой сталкивается почти каждый администратор или разработчик. Кадровые специалисты часто имеют свои представления о том, как должен выглядеть номер приказа: без лидирующих нулей, с суффиксами вроде "-от" или сложными дробями типа "89/1". Как только пользователь вручную вводит номер "99", типовой механизм 1С «затыкается», так как пытается инкрементировать это значение и не находит свободного места в строке или нарушает логику строкового сравнения. Проанализируем, почему это происходит и как решить задачу системно.
Разберем причину сбоя. В платформе 1С номер документа — это строка. Поиск максимального номера для генерации следующего происходит по правилам строковой сортировки. Типовой номер выглядит примерно так: ЗП00-000001. Когда кадровик вводит вручную 99, для системы это значение становится «больше», чем ЗП00-000001, из-за первого символа "9".
Система пытается прибавить единицу к "99", получает "100", но из-за отсутствия префикса и нарушения стандартной длины (которую система ожидает увидеть в соответствии с настройками метаданных), механизм автонумерации не может корректно продолжить последовательность. В результате каждому новому документу предлагается номер "99", который уже занят, и пользователь получает ошибку уникальности.
Это самый правильный и «чистый» способ с точки зрения стабильности системы. Мы оставляем типовой номер 1С в покое (с его нулями и префиксами), а для пользователей выводим в печатные формы «красивый» номер.
Проанализируем шаги реализации:
ПрефиксацияОбъектов.СформироватьНомерДляПечати() или напишем свою логику удаления лидирующих нулей.0000-000089, а на бумаге печатается 89.Если кадровикам нужны специфические суффиксы (например, "89-от"), лучше всего добавить Дополнительный реквизит для документа (через механизм «Дополнительные сведения и реквизиты»). Тогда в печатную форму мы будем подтягивать значение из этого реквизита, если он заполнен, иначе — стандартный номер без нулей.
Если требования пользователей непоколебимы и они хотят видеть короткие номера прямо в форме списка, придется вмешаться в программную логику установки номера. Рассмотрим пример кода, который переопределяет стандартное поведение при создании нового документа.
Воспользуемся аннотацией &Вместо для процедуры ПриУстановкеНовогоНомера. Нам нужно найти максимальный номер за текущий год, очистить его от нецифровых символов, преобразовать в число и прибавить единицу.
&Вместо("ПриУстановкеНовогоНомера")
Процедура Нум_ПриУстановкеНовогоНомера(СтандартнаяОбработка, Префикс)
СтандартнаяОбработка = Ложь; // Отключаем стандартный механизм
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| МАКСИМУМ(Отпуск.Номер) КАК МаксНомер
|ИЗ
| Документ.Отпуск КАК Отпуск
|ГДЕ
| Отпуск.Дата МЕЖДУ &НачалоГода И &КонецГода";
Запрос.УстановитьПараметр("НачалоГода", НачалоГода(Объект.Дата));
Запрос.УстановитьПараметр("КонецГода", КонецГода(Объект.Дата));
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Если Выборка.Следующий() И ЗначениеЗаполнено(Выборка.МаксНомер) Тогда
// Здесь должна быть логика извлечения только цифр
// Допустим, функция ТолькоЦифры() возвращает числовое представление
ЧисловойНомер = ТолькоЦифры(Выборка.МаксНомер);
Объект.Номер = Формат(ЧисловойНомер + 1, "ЧГ=");
Иначе
Объект.Номер = "1";
КонецЕсли;
КонецПроцедуры
Важное предупреждение: Такой подход в лоб имеет существенный недостаток — он не учитывает конкурентную работу пользователей. Если два человека одновременно создадут документ, запрос может вернуть им одинаковый «максимальный» номер. Типовой механизм 1С решает эту проблему на уровне блокировок базы данных. Если вы внедряете свою нумерацию, позаботьтесь о контроле уникальности при записи.
Рассмотрим ситуацию, когда кадровики вводят номера вручную, но мы хотим, чтобы автонумерация продолжала работать хотя бы в фоновом режиме. Можно настроить систему так, чтобы она работала с отдельным префиксом. Посмотрим, как это сделать через событие ПриУстановкеНовогоНомера.
Мы можем принудительно назначать документам префикс, который не используется пользователями вручную, например, "АВ-". В этом случае платформа будет вести отдельный счетчик для этого префикса, и «ручные» номера без префиксов не будут мешать автоматическим. Когда кадровику потребуется изменить номер на свой, он сделает это вручную, не ломая основную ветку нумерации.
Выясним причину, по которой кадровики используют номера типа "89/1". Обычно это связано с тем, что документ был забыт и его нужно «втиснуть» между существующими приказами. Проанализируем пример запроса, который поможет найти следующий номер, даже если в базе присутствуют сложные строковые значения.
Чтобы найти «максимальный» номер среди строк разной длины и с разными символами, в запросе можно использовать конструкцию ПОДОБНО для фильтрации и приведение типов, однако лучше выгружать номера в таблицу значений и обрабатывать их на стороне сервера 1С:
// Пример обработки выборки номеров с суффиксами
МаксЗначение = 0;
Пока Выборка.Следующий() Цикл
ТекущийНомер = Выборка.Номер;
// Удаляем префиксы организации и суффиксы типа "-от"
ЧистаяСтрока = СтрЗаменить(ТекущийНомер, "-от", "");
Попытка
ЧислоНомера = Число(ЧистаяСтрока);
Если ЧислоНомера > МаксЗначение Тогда
МаксЗначение = ЧислоНомера;
КонецЕсли;
Исключение
// Игнорируем номера, которые не приводятся к числу (например, с дробями)
КонецПопытки;
КонецЦикла;
ЭтотОбъект.Номер = Формат(МаксЗначение + 1, "ЧГ=");
Если работа встала, а программировать некогда, выполним следующие действия:
0000-000099.СтрЗаплатать (или написав небольшой скрипт в поле «Выполнить произвольный код») восстановите длину номера.Резюме: Чтобы навсегда забыть о проблемах с нумерацией, проанализируйте требования кадровой службы. В 90% случаев проблему решает скрытие лидирующих нулей только в печатных формах при сохранении эталонного формата в самой базе данных. Это гарантирует стабильную работу платформенных механизмов и полное соответствие бумажного документооборота требованиям предприятия.