Перейти к основному содержанию
`Ctrl`+`K`

# Автонумерация и генерация значений

Автоматическое присвоение значений атрибутам объектов — ключевая функция платформы, обеспечивающая уникальность, последовательность и стандартизацию данных. Документ описывает механизмы автонумерации, генерации штрих-кодов и управления подписями для печати.

## Автонумерация

Автонумерация — процесс автоматической выдачи значения для атрибута класса. В основе лежит выдача порядкового номера (числа), которое может быть преобразовано в значение по маске.

Автоматическая нумерация объектов системы позволяет устанавливать для созданных объектов уникальные коды. При этом создаваемые коды последовательно увеличиваются.

Существует два режима работы автонумерации:

- Без заполнения пропусков.

- С заполнением пропусков.

### Определение разреза автонумерации

Автонумерация в пределах значений одного или нескольких атрибутов класса называется автонумерацией с разрезом. Значение разреза может вычисляться по правилу, указанному в теге `expression`. Если выражение не указано, будет использоваться значение атрибута.

Например, в течение одного дня выдаются номера последовательно, при наступлении следующего дня номера начинают выдаваться заново. Такой разрез называется разрез по дате.

### Настройка автонумерации без разреза

Для автонумерации без разреза в odm-файле класса указываем для атрибута тип `autonum`, далее в блоке `autonum` задаём имя разреза `dimension`:

    <attr name="sNoDep"
          caption="Автонумерация без разреза"
          attribute-type="Varchar"
          type="autoNum"
          isHeadLine="true">
        <autonum id="1">
            <mask>lpad(counter,3,"0")</mask>
            <dimension name="dim1"/>
        </autonum>
    </attr>

### Настройка автонумерации с разрезом

Для настройки разрезов `dimension`:

1. Задайте уникальные имена.

2. Укажите атрибуты разреза. Разрезы указываются из атрибутов класса.

3. При необходимости задайте порядковый номер. Если его не указывать, они будут обрабатываться в алфавитном порядке.

Количество разрезов должно быть `>= 1`.

Указание нескольких разрезов:

    <attr name="sTwoDepExpr"
          caption="Автонумерация с 2 разрезами"
          attribute-type="Varchar"
          type="autoNum">
        <autonum id="3">
            <mask>lpad(counter,3,"0")</mask>
            <dimension name="nNumber"
                       attr="nNumber"
                       order="10" />
            <dimension name="dDate_dim"
                       attr="dDate"
                       order="20">
                <expression>truncDate(dimValue)</expression>
            </dimension>
        </autonum>
    </attr>

Если в настройках автонумерации указан разрез, то автоматически включено заполнение пропусков. Отключить заполнение пропусков можно через свойство `isHoleFill`:

    <attr name="sOneDepNoHoleFill"
          caption="Автонумерация с 1 разрезом без заполнения пропусков"
          attribute-type="Varchar"
          type="autoNum"
          isHeadLine="true">
        <autonum id="4"
                 isHoleFill="false">
            <dimension name="dDate"
                       attr="dDate"
                       order="10"/>
        </autonum>
    </attr>

### Общие настройки

Возможно использовать маски для вывода значения счётчика. Значение, указанное в элементе `mask`, будет передано в обработчик Jexl-скриптов.

Параметр, заменяемый на значение счётчика, называется `counter`.
В Jexl добавлены методы:

- `lpad(string, size, padChar)` — добавление строки символами слева;

- `rpad(string, size, padChar)` — добавление строки символами справа;

- `truncDate(date)` — получение даты на начало дня от переданной;

- `truncYear(date)` — получение даты на начало года от переданной.

В jexl-скрипте можно обращаться к api и pkg объектам.

К значениям атрибутов разреза возможно применение выражений, они указываются в элементе `expression` для `dimension`.

На каждый разрез может быть не больше одного выражения.

Значение, указанное в элементе `expression`, будет передано в обработчик Jexl-скриптов. Параметр, заменяемый на значение атрибута разреза, называется `dimValue`.

    <attr name="sRegNumber"
          attribute-type="Varchar"
          caption="Рег. №"
          order="230"
          type="autoNum"
          isVisible="false"
          isReadOnly="true">
        <autonum>
            <mask>
                var sOTCode = Btk_ObjectTypeApi.load(self.idObjectType()).getByAttrName(\"sCode\");
                if (sOTCode eq \"OperDecisionPrj\" || sOTCode eq \"ProductDecisionPrj\") {
                    counter + \"-Г\"
                } else {
                    counter + \"-Г.\" + Bs_PrjVerApi.load(self.idPrjVer()).getByAttrName(\"sCode\")
                }
            </mask>
            <dimension name="idObjectType" attr="idObjectType" order="1">
                <expression>
                    if (dimValue == null) {
                        null
                    } else {
                        var sCode = Btk_ObjectTypeApi.load(dimValue).getByAttrName(\"sCode\");
                        if (sCode eq \"OperDecisionPrj\" || sCode eq \"OperDecisionWrk\" ||
                            sCode eq \"ProductDecisionPrj\" || sCode eq \"ProductDecisionWrk\"
                        ) 0L else null;
                    }
                </expression>
            </dimension>
        </autonum>
    </attr>

Для обращения к полям класса при вычислении маски используется переменная `self`, которая является объектом типа Aro, поэтому для получения значения атрибута необходимо добавлять в конце скобки (т.к. это метод).
Например: self.sCaption()

После генерации кода необходимо будет выполнить метод `*Dpi.autoNumCreateTable`.

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

Также генерация окружения автонумерации выполняется перед инициализацией первоначальных данных (`init data`), которая вызывается при обновлении проектного jar-кода или при выполнении генерации таблиц в IntelliJ IDEA: `External Tools > Generate Tables`.

Присвоение значения автонумерации происходит в момент сохранения транзакции.

При ручной установке значения автонумерующегося атрибута (при работе из интерфейса) будет задан вопрос:

> «Значение присваивается автоматически в момент сохранения, ввод данных отключит автонумерацию. Продолжить?»

Положительный ответ на вопрос установит значение и отключит автонумерацию объекта. Для повторного включения автонумерации нужно сбросить значение атрибута.

### Автонумерация в миксинах

Возможно задание автонумерации в миксине. Атрибуты, которые объявлены как автонумерующиеся в миксине, но при этом как обычные в целевом классе, получат настройки автонумерации + сквозные таблицы хранения значений автонумерации для всех классов, использующих данный миксин.

Если атрибут объявлен как автонумерующийся и в миксине, и в классе, то будет использована настройка класса.

### Создание окружения автонумерации

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

1. Зайдите в приложение «Настройка системы».

2. Откройте список классов.

3. Переведите фокус на целевой класс. Для данного класса должен стоять признак «Есть автонумерация».

4. Выполните операцию «Создать структуры автонумерации». Данная операция находится под молоточками. При этом произойдёт вызов метода `*Dpi.autoNumCreateTable`.

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

1. Откройте карточку класса.

2. Переведите фокус на целевой атрибут.

3. Выполните операцию «Создать структуру автонумерации». Данная операция вызывает метод `*Dpi.autoNumCreateTableByAttr`.

### Проектное переопределение

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

Проектные настройки хранятся в БД и не сбрасываются при установке обновлений.

Для выполнения проектного переопределения:

1. Зайдите в карточку класса.

2. Выберите автонумерующийся атрибут.

3. Откройте закладку «Настройки автонумерации».

4. На панели открытой закладки нажмите кнопку «Переопределить».

5. Настройте разрезы и маску.

6. Выполните операцию создания окружения нумерации.

#### Настройка счётчиков и данных разрезов

Если автонумерация без разрезов, то она и без заполнения пропусков. Счётчик такой автонумерации хранится в сиквенсе.

Автонумерация с разрезами хранит свои данные в двух таблицах:

- Таблица разрезов. На каждый уникальный набор значений разрезов хранится значение счётчика, маска, признак, что есть пропуски.

- Таблица пропусков. Для каждого разреза хранит информацию о имеющихся пропусках в виде пар значений («значение от» и «значение до»).

Таким образом, для изменения текущего значения счётчика для автонумерации без разрезов достаточно изменить значение сиквенса.

Для автонумерации с разрезами, чтобы изменить счётчик, нужно установить значение в таблице разрезов.

Для настройки:

1. Зайдите в карточку класса.

2. Выберите автонумерующийся атрибут.

3. Откройте закладку «Настройки автонумерации».

4. Откройте закладку «Данные автонумерации».

5. Настройте значение счётчика:

   - Если автонумерация без разрезов, то на детальной закладке будет карточка с одним атрибутом, который показывает текущее значение сиквенса.

   - Если автонумерация с разрезом, то на детальной закладке будут отображены данные из таблицы разрезов и таблицы пропусков. Для изменения счётчика в нужном разрезе указывается значение в поле «Максимальное значение». Если разреза нет, его можно создать. Если удалить разрез, автонумерация начнётся с 1 для этого разреза.

## Автоматическая генерация штрих-кодов объекта

Сервисная возможность при вставке объекта класса формировать ему штрих-код.

Для этого в ODM в теге `Class` есть свойство `barCodeObjectTypeName`, в качестве значения указывается системное имя объектов класса `Bs_BarCodeObjectType`.

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

    Bs_BarCodeObjectTypeApi().register

### Описание работы маски

Если в маске указано: `001-[counter]`, при этом:

- Длина штрих-кода составляет 10 символов.

- Следующее значение счётчика: 12.

Итоговый штрих-код: 001-000012

## Подписи объектов для печати

Сервисная возможность указания типа подписей объекта. Используется при печати отчётов. Позволяет формировать в печатной форме список лиц с местом для подписи.

Список подписей настраивается в коллекции для печатной формы. Список может быть переопределён у объекта. Для хранения подписей печатных бланков используется JSON-контейнер `jSign_dz`.

### Приоритет отображения данных по типу подписи

1. Данные по типу подписи, хранимые в атрибуте объекта класса `jSign_dz` (формируется для всех классов).

2. Данные из настроек подписей в отчёте.

При печати отчёта, если удалось определить сохранённые подписи объекта, то будут переданы настройки подписей на самом отчёте.

Кроме этого, в базовых справочниках реализована возможность формирования комиссий, состав которых может быть передан в отчёт. Подробная настройка комиссий будет рассмотрена в разделе «Прикладная типизация объекта класса».

Данные подписей передаются в параметр `SIGNDATA_DZ`. Представляют собой JSON-объект с ключами:

- `idComission` — идентификатор комиссии. Определяется через тип объекта и подразделение.

- `data` — массив подписей объекта. Каждый элемент представляет собой JSON-объект по типу подписи. Поля:

  - `idBlankSignType` — ИД типа подписи;

  - `idBlankSignTypeMC` — системное имя типа подписи;

  - `idBlankSignTypeHL` — наименование типа подписи;

  - `sPosition` — должность;

  - `sFIO` — Фамилия Имя Отчество;

  - `sBasisDocument` — документ-основание;

  - `dDate` — дата подписи;

  - `idDepartment` — ИД подразделения;

  - `idDepartmentMC` — код подразделения;

  - `idDepartmentHL` — наименование подразделения;

  - `nOrder` — порядковый номер подписи комиссии.

Для работы с атрибутом `jSign_dz` реализован API в пакете `Bs_ObjectSignPkg`.

Если для класса задан `тип объекта`, для работы с подписями можно воспользоваться стандартной закладкой:
`ru.bitec.app.bs.sign.Bs_ObjectSignAvi.List_Master`