Документация для разработчиков

Нумератор

Как очевидно из названия, нумератор отвечает за то, чтобы генерировать номера.

Нумератор получает шаблон номера (содержащий служебные слова) и настройки для слов. Затем у нумератора можно запрашивать следующий номер. Например, если шаблон содержит - {NUMBER} - нумератор каждый раз на запрос следующего номера будет возвращать уникальное последовательное число.

Логика работы

Каждый нумератор содержит в себе генераторы, которые отвечают за парсинг служебных слов в шаблоне номера в зависимости от своих настроек. У генераторов есть привязка к типу нумератора, то есть некоторые генераторы работают только с определенным типом нумератора.

Соответственно, от типа нумератора зависит набор возможных слов для формирования шаблона.

Любой нумератор любого модуля может использовать базовые генераторы - случайный номер, дата, последовательный номер и префикс - и слова {NUMBER}, {DAY}, {MONTH}, {YEAR}, {RANDOM}, {PREFIX}

Функционал нумератора можно расширить, добавив новые классы генераторов и указав им тип нумератора, с которым они могут работать. Так сделано в модулях sale, crm, documentgenerator.

Работа с нумераторами

В идеале, вся работа с нумераторами (CRUD) происходит через класс \Bitrix\Main\Numerator\Numerator.

Старайтесь придерживаться этого принципа.

Создание

use Bitrix\Main\Numerator\Numerator;

$numerator = Numerator::create();

Нумератору нужно указать шаблон номера (состоит из служебных слов (плейсхолдеров)) и настройки для каждого служебного слова в номере (если необходимо). Например, слово {RANDOM} - превратится в рандомные символы; для {RANDOM} можно задать length - число символов в последовательности.

Получить все слова (плейсхолдеры), которые может использовать нумератор типа DOCUMENT

use Bitrix\DocumentGenerator\Driver;
use Bitrix\Main\Numerator\Numerator;

$templateWords = Numerator::getTemplateWordsForType(Driver::NUMERATOR_TYPE);

// Результат
[
    'Bitrix_Main_Numerator_Generator_SequentNumberGenerator' => [
        '{NUMBER}',
    ],
    'Bitrix_Main_Numerator_Generator_DateNumberGenerator' => [
        '{DAY}',
        '{MONTH}',
        '{YEAR}',
    ],
    'Bitrix_Main_Numerator_Generator_RandomNumberGenerator' => [
        '{RANDOM}',
    ],
    'Bitrix_Main_Numerator_Generator_PrefixNumberGenerator' => [
        '{PREFIX}',
    ],
    'Bitrix_DocumentGenerator_Integration_Numerator_DocumentNumberGenerator' => [
        '{CLIENT_ID}',
        '{SELF_ID}',
        '{SELF_COMPANY_ID}',
    ],
];

Для всех типов нумераторов по умолчанию доступны 4 базовых генератора, соответственно, всегда будут доступны слова:

  • {NUMBER} - последовательное число
  • {DAY} - день месяца в момент генерации номера, с ведущим нулем => 01, 15, ...
  • {MONTH} - номер месяца в момент генерации номера, с ведущим нулем => 03, 11, ...
  • {YEAR} - текущий год, на момент генерации номера нумератором => 2018, ...
  • {RANDOM} - случайный набор символов из латинских букв в верхнем регистре и цифр
  • {PREFIX} - указанный фиксированный набор символов

Документные нумераторы (тип DOCUMENT) могут дополнительно использовать:

  • {CLIENT_ID} - ID клиента
  • {SELF_ID} - ID сущности, которая является провайдером данных (зависит от того, что будет передано нумератору при формировании номера)
  • {SELF_COMPANY_ID} - ID компании

В CRM (для нумераторов типа CRM_QUOTE, CRM_INVOICE) можно дополнительно использовать слова:

  • {INVOICE_ID} Номер счета
  • {USER_ID_INVOICES_COUNT} - Id пользователя и число его счетов
  • {QUOTE_ID} - Номер предложения
  • {USER_ID_QUOTES_COUNT} - Id пользователя и число его предложений

В магазине (для нумераторов типа ORDER):

  • {USER_ID_ORDERS_COUNT} - Id пользователя и число его заказов
  • {ORDER_ID} - Номер заказа

Получить все настройки для создания нумератора типа DOCUMENT

use Bitrix\DocumentGenerator\Driver;
use Bitrix\Main\Numerator\Numerator;

$settings = Numerator::getSettingsFields(Driver::NUMERATOR_TYPE);

// Результат
[
    'settingsFields' => [
        'Bitrix_Main_Numerator_Numerator' => [
            ['settingName' => 'name', 'type' => 'string', 'default' => 'Нумератор 1', 'title' => 'Название нумератора', ],
            ['settingName' => 'template', 'type' => 'string', 'title' => 'Шаблон номера',],
        ],
        'Bitrix_Main_Numerator_Generator_SequentNumberGenerator' => [
            ['settingName' => 'start', 'type' => 'int', 'default' => 1, 'title' => 'Начинать последовательный номер с',],
            ['settingName' => 'step', 'type' => 'int', 'default' => 1, 'title' => 'Увеличивать последовательный номер на',],
            ['settingName' => 'periodicBy', 'type' => 'array', 'title' => 'Период работы нумератора', 'values' => [
                ['settingName' => 'default', 'value' => '', 'title' => 'Постоянно',],
                ['settingName' => 'day', 'value' => 'day', 'title' => 'В пределах дня',],
                ['settingName' => 'month', 'value' => 'month', 'title' => 'В пределах месяца',],
                ['settingName' => 'year', 'value' => 'year', 'title' => 'В пределах года',],],
            ],
            ['settingName' => 'timezone', 'type' => 'array', 'values' => [...]],
            ...,
        ],
        ...,
    ],
    'settingsWords' => [
        'Bitrix_Main_Numerator_Generator_SequentNumberGenerator' => ['{NUMBER}' => 'Последовательный номер',],
        'Bitrix_Main_Numerator_Generator_DateNumberGenerator' => ['{DAY}' => 'Текущий день', '{MONTH}' => 'Текущий месяц', '{YEAR}' => 'Текущий год',],
        'Bitrix_Main_Numerator_Generator_RandomNumberGenerator' => ['{RANDOM}' => 'Случайный номер',],
        'Bitrix_Main_Numerator_Generator_PrefixNumberGenerator' => ['{PREFIX}' => 'Префикс',],
    ]
];

settingsWords - собственно, слова для шаблона (Numerator::getTemplateWordsForType('DOCUMENT'))

settingsFields - обычно используются для формирования html формы, поэтому так много указаний. На основании типов настроек генерируется код для инпутов, дропдаунов, заголовки полей формы, заполняются дефолтные значения и т.д.

Сохранение нумератора

В итоге, создание нумератора, установка настроек и сохранение выглядят так:

use Bitrix\Main\Numerator\Numerator;
use Bitrix\Main\Numerator\Generator;

$config = [
    Numerator::getType() => [
        'name' => 'my awesome numerator',
        'template' => '{PREFIX}__{YEAR}/{NUMBER}--{RANDOM}',
    ],
    Generator\RandomNumberGenerator::getType() => [
        'length' => '6',
    ],
    Generator\SequentNumberGenerator::getType() => [
        'start' => '3',
        'step' => '2',
    ],
    Generator\PrefixNumberGenerator::getType()  => [
        'prefix' => 'test',
    ],
];

$numerator = Numerator::create();
$numerator->setConfig($config);
/** @var \Bitrix\Main\Entity\AddResult $result **/
$result = $numerator->save();

Настройки

use Bitrix\Main\Numerator\Numerator;
use Bitrix\Main\Numerator\Generator;

// Bitrix_Main_Numerator_Numerator
Numerator::getType() => [
   [
       'name', // Название нумератора - ОБЯЗАТЕЛЬНОЕ ПОЛЕ
       'template' // Шаблон номера - ОБЯЗАТЕЛЬНОЕ ПОЛЕ
   ],
],

// Порядковый номер - {NUMBER}
// Bitrix_Main_Numerator_Generator_SequentNumberGenerator

Generator\SequentNumberGenerator::getType() => [
   [
       'start', // С какого числа начинать
       'step', // Шаг для увеличения номера
       'periodicBy', // ['day', 'month', 'year'] - Сбрасывать счетчик в start при наступлении нового периода
       'timezone', // По какому часовому поясу определять наступление нового периода (дня и т.д.)
                   // ['', 'Pacific/Midway', ...] - значения из \CTimeZone::GetZones()
       'isDirectNumeration', // boolean, Использовать сквозную нумерацию или иметь независимые счетчики для каждой компании
   ],
],

// Случайный номер из букв латинского алфавита в верхнем регистре и цифр - {RANDOM}
// Bitrix_Main_Numerator_Generator_RandomNumberGenerator

Generator\RandomNumberGenerator::getType() => [
   [
       'length', // Длина номера
   ],
],

// Строка символов - {PREFIX}
// Bitrix_Main_Numerator_Generator_PrefixNumberGenerator

Generator\PrefixNumberGenerator::getType() => [
   [
       'prefix', // Строка
   ],
],

// Дата - {DAY}, {MONTH}, {YEAR}
// Bitrix_Main_Numerator_Generator_DateNumberGenerator формат дат на данный момент не настраивается

Получение существующего нумератора по ID

use Bitrix\Main\Numerator\Numerator;

$numerator = Numerator::load($numeratorId);

Получение первого существующего нумератора по его типу

$numerator = \Bitrix\Main\Numerator\Numerator::getOneByType('ORDER');

Получение списка нумераторов по типу

$numerator = \Bitrix\Main\Numerator\Numerator::getListByType('ORDER');

Получение следующего номера у нумератора

$nextNumber = $numerator->getNext();

Изменение настроек нумератора по ID

use Bitrix\Main\Numerator\Numerator;

$numerator = Numerator::load($numeratorId);
$config = $numerator->getConfig();
$config[Numerator::getType()]['name'] = 'updated name';
/*** @var \Bitrix\Main\Entity\UpdateResult|Result $result **/
$result = Numerator::update($id, $config);

Передача контекста

Иногда нумератор в общем случае не знает, на что заменить некоторое служебное слово в шаблоне (например, {INVOICE_ID} - номер счета для нумератора в срм). Поэтому, нумератору нужен некий контекст или источник данных. (Для нумераторов, использующих динамически конфигурируемые генераторы, реализующие интерфейс DynamicConfigurable).

Контекст можно передать несколькими способами.

// вторым параметром в Numerator::load
\Bitrix\Main\Numerator\Numerator::load($numeratorId, $source = null);

// имея нумератор, установить ему контекст
$numerator->setDynamicConfig($dynamicConfig);

Хеш нумератора

Нумератор, содержащий служебное слово {NUMBER} в шаблоне, может одновременно отвечать за несколько последовательных номеров (у него будет несколько "внутренних счетчиков"). В общем случае, запрашивая следующий номер у нумератора, мы будем получать последовательно увеличивающееся число.

use Bitrix\Main\Numerator\Numerator;

$numerator = Numerator::create();
$numerator->setConfig([
	Numerator::getType() => [
		'name' => 'test sequence',
		'template' => '{NUMBER}',
	],
]);
$result = $numerator->save();
$numerator = Numerator::load($result->getId());
echo $numerator->getNext() . PHP_EOL;
$numerator = Numerator::load($result->getId());
echo $numerator->getNext() . PHP_EOL;
$numerator = Numerator::load($result->getId());
echo $numerator->getNext() . PHP_EOL;

// Получим
// 1
// 2
// 3

Если же нумератору указывать хеш (строку) и запрашивать номер для разного хеша - мы получим независимые счетчики и сможем получать номера у каждого из них отдельно.

use Bitrix\Main\Numerator\Numerator;

$numerator = Numerator::create();
$numerator->setConfig([
	Numerator::getType() => [
		'name' => 'sequence',
		'template' => '{NUMBER}',
	],
]);
$result = $numerator->save();
$numerator = Numerator::load($result->getId());
echo $numerator->getNext('A') . PHP_EOL;
$numerator = Numerator::load($result->getId());
echo $numerator->getNext('B') . PHP_EOL;
$numerator = Numerator::load($result->getId());
echo $numerator->getNext('A') . PHP_EOL;

// Получим
// 1
// 1
// 2

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

Хеш можно установить несколькими способами.

(Для нумераторов, использующих генераторы, реализующие интерфейс Sequenceable)

use Bitrix\Main\Numerator\Numerator;

// вторым параметром в Numerator::load в виде объекта
// реализующего интерфейс Hashable, возвращающего хеш строкой в $hashable->getHash()
Numerator::load($numeratorId, $hashable);

// передать хеш в getNext в виде строки
$hash = 'MANAGER_42';
$numerator->getNext($hash)

// установить хеш через сеттер в виде объекта Hashable
$numerator->setHash($hashable);

Пользовательские комментарии

Мы будем рады, если разработчики добавят свои комментарии по практическому использованию методов системы.

Для этого нужно всего лишь авторизоваться на сайте

Но помните, что Пользовательские комментарии, несмотря на модерацию, не являются официальной документацией. Ответственность за их использование несет сам пользователь.

Также Пользовательские комментарии не являются местом для обсуждения функционала. По подобным вопросам обращайтесь на форумы.
© «Битрикс», 2001-2019, «1С-Битрикс», 2019
Наверх