При переходе с конфигурации «Зарплата и управление персоналом» редакции 2.5 на редакцию 3.0 многие пользователи и кадровые специалисты сталкиваются с изменением логики работы нумераторов. В прежней версии программы была предусмотрена опция «Единый нумератор», которая позволяла вести сквозную нумерацию для всех типов кадровых приказов. В 1С:ЗУП 3.0 разработчики изменили этот подход: по умолчанию для каждого вида кадрового документа (прием на работу, кадровый перевод, увольнение) создается собственный независимый нумератор.
Попытки кадровиков вручную менять автонумерованные значения, добавлять суффиксы или буквы (например, «0000-000001ПР») часто приводят к тому, что стандартная автонумерация платформы сбивается. Разберем, почему происходят сбои, как правильно использовать штатные механизмы программы и как реализовать единую нумерацию доработкой на уровне кода.
Проанализируем алгоритм работы платформы 1С при присвоении номеров документам. Номер кадрового документа хранится как строка фиксированной длины и состоит из служебных префиксов организации и информационной базы, за которыми следует порядковое число с лидирующими нулями.
Когда создается новый документ, система выполняет следующие шаги:
Если пользователь вручную редактирует номер (удаляет лидирующие нули, меняет дефисы или добавляет буквенные символы), строковая сортировка в СУБД начинает работать иначе. Номер с буквенным индексом может стать «максимальным» навсегда. В результате при создании следующих документов система перестает наращивать номер или постоянно выдает ошибку неуникальности.
Прежде чем переходить к доработке конфигурации, рассмотрим возможности, которые предоставляет типовая программа без изменения кода.
ПриемНаРаботу, КадровыйПеревод, Увольнение) присутствует специальное поле «Печатать как». Оно позволяет оставить системный номер документа стандартным (чтобы не ломать автонумерацию), а в печатные формы и отчетность выводить требуемый индекс или номер с буквами.Если организации необходима строгая сквозная нумерация по всем кадровым документам в базе, решим задачу с помощью создания подписки на событие. Этот способ подходит для реализации в расширении конфигурации или в основной конфигурации.
Рассмотрим порядок действий по шагам:
ПриУстановкеНовогоНомера.ДокументОбъект.ПриемНаРаботу, ДокументОбъект.КадровыйПеревод, ДокументОбъект.Увольнение, а также их списочные формы ДокументОбъект.ПриемНаРаботуСписком, ДокументОбъект.КадровыйПереводСписком и ДокументОбъект.УвольнениеСписком.Посмотрим на пример кода процедура-обработчика:
Процедура УстановкаНомераПоКадровымДокументамПриУстановкеНовогоНомера(Источник, СтандартнаяОбработка, Префикс) Экспорт
// Получаем максимальный последний кадровый номер среди всех типов кадровых документов
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| МАКСИМУМ(НомераТЗ.Номер) КАК Номер
|ИЗ
| (ВЫБРАТЬ
| МАКСИМУМ(ПриемНаРаботу.Номер) КАК Номер
| ИЗ
| Документ.ПриемНаРаботу КАК ПриемНаРаботу
| ГДЕ
| ПриемНаРаботу.Организация = &Организация
| И ГОД(ПриемНаРаботу.Дата) = &Год
| ИМЕЮЩИЕ
| НЕ МАКСИМУМ(ПриемНаРаботу.Номер) ЕСТЬ NULL
|
| ОБЪЕДИНИТЬ ВСЕ
|
| ВЫБРАТЬ
| МАКСИМУМ(Увольнение.Номер)
| ИЗ
| Документ.Увольнение КАК Увольнение
| ГДЕ
| Увольнение.Организация = &Организация
| И ГОД(Увольнение.Дата) = &Год
| ИМЕЮЩИЕ
| НЕ МАКСИМУМ(Увольнение.Номер) ЕСТЬ NULL
|
| ОБЪЕДИНИТЬ ВСЕ
|
| ВЫБРАТЬ
| МАКСИМУМ(КадровыйПеревод.Номер)
| ИЗ
| Документ.КадровыйПеревод КАК КадровыйПеревод
| ГДЕ
| КадровыйПеревод.Организация = &Организация
| И ГОД(КадровыйПеревод.Дата) = &Год
| ИМЕЮЩИЕ
| НЕ МАКСИМУМ(КадровыйПеревод.Номер) ЕСТЬ NULL
|
| ОБЪЕДИНИТЬ ВСЕ
|
| ВЫБРАТЬ
| МАКСИМУМ(УвольнениеСписком.Номер)
| ИЗ
| Документ.УвольнениеСписком КАК УвольнениеСписком
| ГДЕ
| УвольнениеСписком.Организация = &Организация
| И ГОД(УвольнениеСписком.Дата) = &Год
| ИМЕЮЩИЕ
| НЕ МАКСИМУМ(УвольнениеСписком.Номер) ЕСТЬ NULL
|
| ОБЪЕДИНИТЬ ВСЕ
|
| ВЫБРАТЬ
| МАКСИМУМ(КадровыйПереводСписком.Номер)
| ИЗ
| Документ.КадровыйПереводСписком КАК КадровыйПереводСписком
| ГДЕ
| КадровыйПереводСписком.Организация = &Организация
| И ГОД(КадровыйПереводСписком.Дата) = &Год
| ИМЕЮЩИЕ
| НЕ МАКСИМУМ(КадровыйПереводСписком.Номер) ЕСТЬ NULL
|
| ОБЪЕДИНИТЬ ВСЕ
|
| ВЫБРАТЬ
| МАКСИМУМ(ПриемНаРаботуСписком.Номер)
| ИЗ
| Документ.ПриемНаРаботуСписком КАК ПриемНаРаботуСписком
| ГДЕ
| ПриемНаРаботуСписком.Организация = &Организация
| И ГОД(ПриемНаРаботуСписком.Дата) = &Год
| ИМЕЮЩИЕ
| НЕ МАКСИМУМ(ПриемНаРаботуСписком.Номер) ЕСТЬ NULL) КАК НомераТЗ
|
|ИМЕЮЩИЕ
| НЕ МАКСИМУМ(НомераТЗ.Номер) ЕСТЬ NULL";
Запрос.УстановитьПараметр("Организация", Источник.Организация);
Запрос.УстановитьПараметр("Год", Год(Источник.Дата));
РезультатЗапроса = Запрос.Выполнить();
Если НЕ РезультатЗапроса.Пустой() Тогда
СтандартнаяОбработка = Ложь;
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
// Выделяем числовую часть номера с помощью БСП
НомерБезНолейИПрефикса = Число(ПрефиксацияОбъектовКлиентСервер.НомерНаПечать(Выборка.Номер, Истина, Истина));
НомерБезНолейИПрефикса = НомерБезНолейИПрефикса + 1;
// Формируем новый номер с сохранением префикса и дополнение нулями
Источник.Номер = Префикс + СтроковыеФункцииКлиентСервер.ДополнитьСтроку(Строка(НомерБезНолейИПрефикса), 6, "0", "Слева");
КонецЕсли;
КонецПроцедуры
Разберем особенности этой реализации:
ПрефиксацияОбъектовКлиентСервер.НомерНаПечать() (в решениях на базе ERP аналогичный метод может называться ПолучитьНомерНаПечать()) очищает строку от лидирующих нулей и префиксов, оставляя чистое числовое значение.СтроковыеФункцииКлиентСервер.ДополнитьСтроку() восстанавливает требуемую длину номера, добавляя нули слева.СтандартнаяОбработка = Ложь отменяет базовое назначение номера платформой, подменяя его сформированным значением.Благодаря данному алгоритму при создании любого из описанных документов система проверяет сквозную историю номеров за год и назначает следующий по порядку номер вне зависимости от типа кадрового приказа.