Как настроить автонумерацию документов в 1С:Документооборот по нестандартному алгоритму "Порядковый номер дня в году / Индекс внутри дня"?

Программист 1С v8.3 (Управляемые формы) 1С:Документооборот Управленческий учет IT и автоматизация бизнеса
← На главную

Многие пользователи и компании сталкиваются с необходимостью настройки автонумерации документов в системе 1С:Документооборот по уникальным, специфическим алгоритмам, которые выходят за рамки стандартных настроек. Рассмотрим ситуацию, когда требуется формировать номер документа в формате, например, "Номер дня в году / Порядковый номер документа за этот день". Допустим, мы хотим получить номера вида: 01.01.22г. № 1/01, № 1/02, № 1/03; 02.01.22г. № 2/01, № 2/02, № 2/03. Попробуем разобраться, как реализовать такую логику, учитывая ограничения типового функционала.

Ограничения стандартных настроек автонумерации в 1С:Документооборот

Прежде всего, следует отметить, что стандартные настройки автонумерации документов в 1С:Документооборот, к сожалению, не позволяют реализовать такую сложную логику без доработки. Типовые нумераторы предлагают периодичность по "Году", "Кварталу", "Месяцу" или "Дню", но не предусматривают одновременное использование нескольких счетчиков в одном номере (например, "порядковый номер дня в году" и "порядковый номер за день") или использование сложных выражений для формирования частей номера. Поэтому, если вы планируете использовать подобный алгоритм, будьте готовы к тому, что потребуется вмешательство программиста.

Даже если бы мы могли привязать два нумератора к одному виду документа, это не решило бы проблему автоматически. Стандартный механизм не умеет комбинировать их таким образом, чтобы первый нумератор давал номер дня в году, а второй — порядковый номер внутри этого дня с автоматическим сбросом. В результате, для достижения желаемого формата номера, нам придется обратиться к программной реализации.

Реализация нестандартной автонумерации через скрипты в нумераторах

В современных версиях 1С:Документооборот, начиная с 2.1 и далее в 3.0, имеется возможность использовать пользовательские выражения на встроенном языке 1С непосредственно в справочнике Нумераторы. Это очень мощный инструмент, который позволяет расширить логику формирования номера, не снимая при этом конфигурацию с поддержки. Это означает, что мы можем добавить необходимый код, не изменяя саму структуру конфигурации, что упрощает обновления системы в будущем.

Разберем по шагам, как это можно реализовать:

  1. Создание нумератора: Мы создаем новый нумератор или модифицируем существующий для конкретного вида документа.
  2. Использование выражения на встроенном языке: В поле настройки шаблона номера, где указываются префиксы, суффиксы и порядковый номер, мы можем вставить выражение. Это выражение будет вычисляться в момент присвоения номера документу.
  3. Расчет номера дня от начала года: Для получения номера дня от начала года мы можем использовать встроенную функцию ДеньГода() или вычислить разность дат. Например, если у нас есть дата документа ДатаДокумента, то номер дня в году можно получить так: ДеньГода(ДатаДокумента) Если нам нужен двузначный формат с лидирующим нулем (например, "01", "02"), нам потребуется дополнительное форматирование: Формат(ДеньГода(ДатаДокумента), "ЧЦ=2; ЧВН=; ЧС=0")
  4. Поиск последнего номера и инкремент: Самая сложная часть — это получение порядкового номера в сутках. Для этого система должна будет программно выполнить следующие действия:
    1. Определить текущую дату (дату регистрации документа).
    2. Найти в базе данных все документы того же вида, зарегистрированные в течение текущих суток.
    3. Извлечь из номеров этих документов их суффикс (индекс после дроби), например, "01", "02".
    4. Найти максимальный суффикс и увеличить его на единицу, чтобы получить следующий порядковый номер.
    5. Если документы за текущие сутки еще не регистрировались, начать с "01".

    Примерная логика скрипта внутри нумератора (псевдокод, требующий адаптации под конкретный объект ДокументОбъект и его метаданные):

    
    // Получаем дату документа, для которого формируется номер
    ДатаДокумента = Параметры.ДокументОбъект.Дата; 
            
    // Формируем порядковый номер дня в году
    НомерДняГода = Формат(ДеньГода(ДатаДокумента), "ЧЦ=2; ЧВН=; ЧС=0");
            
    // Определяем начало и конец текущих суток
    НачалоДня = НачалоДня(ДатаДокумента);
    КонецДня = КонецДня(ДатаДокумента);
            
    // Запрос для поиска последнего номера за текущий день
    // Это пример логики, требующий более детальной реализации с учетом специфики запросов и полей номера
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ 
        |    МАКСИМУМ(Документ.Номер) КАК ПоследнийНомер
        |ИЗ
        |    Документ.НашВидДокумента КАК Документ
        |ГДЕ
        |    Документ.Дата МЕЖДУ &НачалоДня И &КонецДня
        |    И Документ.ВидДокумента = &ВидДокумента"; // Предполагается поле для вида документа
                
    Запрос.УстановитьПараметр("НачалоДня", НачалоДня);
    Запрос.УстановитьПараметр("КонецДня", КонецДня);
    Запрос.УстановитьПараметр("ВидДокумента", Параметры.ДокументОбъект.ВидДокумента); // Пример
                
    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();
            
    ПорядковыйИндекс = 0;
    Если Выборка.Следующий() И Не Пустая(Выборка.ПоследнийНомер) Тогда
        // Извлекаем числовую часть после дроби
        // Предполагаем, что формат номера уже "X/YY"
        ЧастиНомера = СтрРазделить(Выборка.ПоследнийНомер, "/", Ложь);
        Если ЧастиНомера.Количество() > 1 Тогда
            ПоследнийИндексСтрока = ЧастиНомера[ЧастиНомера.Количество() - 1];
            ПорядковыйИндекс = Число(ПоследнийИндексСтрока);
        КонецЕсли;
    КонецЕсли;
            
    ПорядковыйИндекс = ПорядковыйИндекс + 1;
    ИндексСтрока = Формат(ПорядковыйИндекс, "ЧЦ=2; ЧВН=; ЧС=0");
            
    Возврат НомерДняГода + "/" + ИндексСтрока;
    

    Обратите внимание, что этот код — лишь концептуальный пример. Реальная реализация потребует тщательной работы с запросами, учетом возможных ошибок парсинга номеров и оптимизации для производительности, особенно при большом объеме документов.

Различия в версиях 1С:Документооборот 2.1 и 3.0

В 1С:Документооборот 3.0 архитектура нумерации претерпела изменения. Настройки нумерации теперь вынесены в отдельные блоки управления правилами обработки документов, что предоставляет большую гибкость. Появились "Разрезы нумерации", которые позволяют более детально настроить условия для формирования номера. Однако, для настолько специфического алгоритма, как "Номер дня в году / Порядковый номер в сутках", даже в версии 3.0 программное расширение логики все равно потребуется. Разница будет заключаться в том, как именно эта логика будет встраиваться в новые механизмы обработки событий при регистрации документов и работы с разрезами нумерации. Принципы написания скриптов остаются схожими, но точки интеграции могут отличаться.

Проблема уникальности и контроля дублей

При использовании нестандартных алгоритмов нумерации, таких как "НомерДня/Индекс", стандартный механизм контроля уникальности номеров в 1С может работать некорректно. Типовой механизм рассчитан на линейное приращение номера и может не распознавать числовую часть номера, разделённую символом дроби или другими нестандартными разделителями. Это создает риск возникновения "дырок" в нумерации или, что хуже, задвоения номеров, особенно при одновременной работе нескольких пользователей.

Для предотвращения таких ситуаций программисту необходимо будет:

  1. Отключить стандартный контроль уникальности: В некоторых случаях может потребоваться отключить типовой контроль уникальности номера для данного вида документа.
  2. Реализовать собственный обработчик уникальности: Мы должны будем прописать свой обработчик события ПередЗаписью или ПриЗаписи для объекта документа. В этом обработчике мы будем выполнять запрос к базе данных, чтобы проверить, существует ли уже документ с таким же сформированным номером. Если такой номер найден, необходимо выдать пользователю ошибку и предложить переформировать номер или изменить его вручную.

Примерный псевдокод для проверки уникальности:


// В обработчике события ПередЗаписью() документа

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |    Документ.Ссылка
    |ИЗ
    |    Документ.НашВидДокумента КАК Документ
    |ГДЕ
    |    Документ.Номер = &Номер
    |    И Документ.Ссылка <> &Ссылка"; // Исключаем сам себя при изменении

Запрос.УстановитьПараметр("Номер", ЭтотОбъект.Номер);
Запрос.УстановитьПараметр("Ссылка", ЭтотОбъект.Ссылка);

Если Не Запрос.Выполнить().Пустой() Тогда
    Отказ = Истина;
    Сообщить("Документ с таким номером уже существует!", СтатусСообщения.Важное);
КонецЕсли;

Индексы нумерации как частичное решение

В 1С:Документооборот существует штатный функционал "Индексы нумерации". Обычно они используются для добавления префиксов или суффиксов к номеру в зависимости от контрагента, подразделения или вида документа. Теоретически, можно было бы использовать этот механизм, если бы мы могли программно ежедневно обновлять некий служебный индекс, который бы представлял собой номер дня в году. Однако, для связки "Номер дня года + Индекс внутри дня" этого все равно недостаточно без написания дополнительного кода.

То есть, мы могли бы настроить индекс, который ежедневно сбрасывается и содержит номер дня, но тогда все документы за этот день будут иметь один и тот же порядковый номер (например, № 01.01.22г. 1). Для получения инкрементальной части номера (01, 02, 03) внутри одного дня, мы все равно вернемся к необходимости программной доработки.

Риски при изменении алгоритма "на лету"

Критически важно учитывать риски, если ваша организация уже вела учет документов в текущем году и решила перейти на новую схему нумерации. Автоматическое пересчитывание старых номеров под новый формат 1С не умеет выполнять самостоятельно. Это может привести к следующим проблемам:

  1. Конфликт существующих номеров: Если новый алгоритм начнет формировать номера, которые уже существуют в базе данных по старому формату, возникнут ошибки уникальности.
  2. Сбои при поиске "следующего" номера: Программный поиск "последнего" номера для инкремента может давать сбои, если в базе перемешаны номера старого и нового образца. Например, если в базе есть "№ 100" (старый) и "№ 1/01" (новый), и наш скрипт ищет максимальный порядковый номер, он может неправильно интерпретировать старый номер.

Для минимизации этих рисков при внедрении новой нумерации в середине периода рекомендуем:

Альтернатива через дополнительные реквизиты

Если мы хотим избежать глубоких изменений в типовом механизме нумерации и минимизировать риски, существует элегантное альтернативное решение. Мы можем сохранить стандартный системный номер документа (который будет просто линейно увеличиваться) и создать дополнительный строковый реквизит для документа.

Этот дополнительный реквизит будет использоваться исключительно для визуального отображения нужного формата номера в печатных формах, реестрах или списках документов. Заполнение этого реквизита будет происходить в момент регистрации документа с помощью простого расширения конфигурации или скрипта, который будет вызываться при записи документа.

Преимущества такого подхода:

Для реализации этого метода:

  1. Создаем новый дополнительный реквизит для нужного вида документа (например, с именем НомерДополнительный, тип — Строка).
  2. В модуле объекта документа или через механизм подписок на события (в 1С:Документооборот 3.0 это будет часть правил обработки документов) пишем код, который будет формировать нужный номер по алгоритму "Номер дня в году / Индекс внутри дня" и записывать его в созданный дополнительный реквизит.
  3. Настраиваем печатные формы, отчеты и списки так, чтобы они отображали значение из реквизита НомерДополнительный вместо или в дополнение к стандартному номеру документа.

Этот подход позволяет удовлетворить требование к отображению номера в нужном формате, не вмешиваясь в базовые механизмы нумерации 1С:Документооборот, что является наиболее безопасным и рекомендуемым способом для нестандартных задач.

Заключение

В итоге, для настройки автонумерации документов в 1С:Документооборот по алгоритму "Порядковый номер дня в году / Индекс внутри дня" потребуется программирование. Стандартными средствами реализовать это невозможно. Мы рассмотрели два основных пути: использование скриптов в нумераторах (для чего нужен программист) или создание дополнительного реквизита с программным заполнением. Выбор конкретного метода будет зависеть от сложности требований, версии 1С:Документооборот и готовности к внесению изменений в конфигурацию. В любом случае, при возникновении подобных задач всегда лучше обращаться к опытным специалистам, которые смогут реализовать функционал качественно и с учетом всех нюансов вашей конфигурации и бизнес-процессов.

← На главную