Numerator
Модуль Numerator генерирует последовательные, читаемые человеком номера и коды объектов — номера заказов, номера счетов, коды контрагентов и подобные. Для каждого вида объектов ведётся отдельный счётчик, к выдаваемому значению добавляется необязательный префикс-серия и фиксированное число ведущих нулей, а сама генерация устойчива к одновременному созданию объектов несколькими пользователями: повторных и пропущенных номеров не возникает.
Нумератор
Нумератор — это объект-настройка класса Numerator, то есть один счётчик, общий для нескольких объектов. Его настройки:
| Свойство | Значение |
|---|---|
name[Numerator] | Наименование, показываемое при выборе нумератора |
series[Numerator] | Серия — префикс, добавляемый к каждому выдаваемому значению (может быть пустым) |
minValue[Numerator] | Начальное значение счётчика; при создании нумератора в него записывается curValue[Numerator] |
maxValue[Numerator] | Наибольшее допустимое значение; когда curValue[Numerator] его достигает, генерация прекращается и выдаётся сообщение |
stringLength[Numerator] | Длина, до которой счётчик дополняется ведущими нулями |
curValue[Numerator] | Текущее значение счётчика — номер, который будет выдан следующим |
Очередное значение составляется из series[Numerator] и следующего за ним curStringValue[Numerator], где curStringValue[Numerator] — это curValue[Numerator], записанное как строка и дополненное слева нулями 0 до stringLength[Numerator] символов. Для нумератора с серией WKO, текущим значением 42 и длиной 6 выдаётся значение WKO000042.
Выдача очередного значения
Два действия выдают текущее значение и продвигают счётчик; различаются они тем, как удерживают счётчик при одновременных сохранениях.
incrementValueSession[Numerator] продвигает счётчик в текущей сессии, поэтому выдача номера и сохранение объекта происходят в одной транзакции. Когда два пользователя сохраняют одновременно, обе транзакции меняют curValue[Numerator] одной и той же строки, и вторая получает CONFLICT UPDATE; платформа автоматически откатывает её и проводит заново, без участия пользователя. Пользователь замечает лишь чуть более медленное сохранение, а нумерация остаётся без пропусков.
incrementValue[Numerator] продвигает счётчик в отдельной короткой транзакции и передаёт выданное значение через incrementedValue[]. Так блокировка строки счётчика выносится из основной транзакции сохранения объекта, что сужает окно для конфликта; взамен номер расходуется даже тогда, когда объект в итоге не сохранён, поэтому в нумерации становятся возможны пропуски.
Оба действия выдают сообщение и не выдают значения, как только curValue[Numerator] достигает maxValue[Numerator].
Нумерация класса
Набор метакодов подключает нумерацию к прикладному классу. Свойства, хранящие номер, помещаются в системную группу numbered.
| Метакод | Что добавляет классу |
|---|---|
@defineNumbered(class, stype) | Хранимые свойства number (строка) и series (типа stype), а также seriesNumber — их конкатенацию, материализованную и проиндексированную как составной ключ для поиска |
@defineNumerated(class) | Ссылку numerator на классе и событие, заполняющее number и series из неё (через incrementValueSession[Numerator]) сразу после того, как нумератор задан, а номер не введён вручную или импортом |
@defineNumeratedDefault(class, caption, series) | Всё, что добавляет @defineNumerated, плюс нумератор по умолчанию для класса, выбираемый на форме defaultNumerators и автоматически проставляемый каждому новому объекту; начальный нумератор (caption, series, диапазон 1..99999, длина 5) заводится через loadDefaultNumerators |
@defineNumeratedID(object, caption) | Нумератор по умолчанию, чьё выданное значение записывается в собственный id объекта вместо отдельного number — для объектов, чей код является их идентификатором |
@defineNumbered дополнительно нормализует введённые номер и серию; этим управляют три настройки на форме options: useLoweredNumber[] переводит номер в нижний регистр, useUpperedSeries[] переводит серию в верхний, а из номера убираются пробелы, если не установлена keepNumberSpaces[].
Когда порядок сохранения не должен зависеть от счётчика — чтобы снизить число конфликтов на активно используемом нумераторе — @addEventGenerateNumberOnForm(form, object, class) добавляет событие, срабатывающее перед сохранением формы: пока включена настройка generateNumberOnForm[], оно выдаёт номер через incrementValue[Numerator] (вариант с отдельной транзакцией из раздела выше), а не во время самого сохранения.
Нумераторы по умолчанию
loadDefaultNumerators — это абстрактное действие-список, которое метакоды заведения расширяют, чтобы создать начальные нумераторы на чистой базе данных; оно встроено в механизм начальных данных платформы. Форма numerators управляет каталогом нумераторов, а defaultNumerators — добавленная в группу навигатора Справочники — собирает выбор нумератора по умолчанию для каждого класса, настроенного через @defineNumeratedDefault или @defineNumeratedID.