Documentation

Numerator

As evident from the name, numerator is responsible for generating numbers.

Numerator receives a template number (containing service words) and words settings. Then the next number can be requested from numerator. For example, when template contains - {NUMBER} - numerator will return unique sequence number for each next number query.

Behaviour

Each numerator contains generators responsible for parsing of service words in the number template depending on its settings. Generator has association to numerator type, meaning that generators are operating only with specific numerator type.

Accordingly, set of possible words for template formatting depends on numerator type.

Any numerator for any number can use base generators - random number, date, sequence number and prefix - as well as words {NUMBER}, {DAY}, {MONTH}, {YEAR}, {RANDOM}, {PREFIX}

Numerator features can be expanded, by adding new generator classes and specifying type of numerator to be handled by such classes. This is done for the modules [link=58837]sale[/link], [link=61451]crm[/link], [link=108333]documentgenerator[/link].

Handling numerators

Ideally, all handling of numerators (CRUD) is performed via the class \Bitrix\Main\Numerator\Numerator.

Try to follow this principle as well.

Creating

use Bitrix\Main\Numerator\Numerator;

$numerator = Numerator::create();

Numerator must contain template number (consist from service words (placeholders)) and settings or each service word in the number (when required). For example, the word {RANDOM} - is converted into random characters; length must be specified for {RANDOM}

Get all words (placeholders), which numerator type DOCUMENT can use

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}',
    ],
];

Four base generators are available for all types of numerators by default. Accordingly, the following words are always available:

  • {NUMBER} - sequence number
  • {DAY} - day of month at the moment of number generation, with leading zero => 01, 15, ...
  • {MONTH} - number of the month at the moment of number generation, with leading zero => 03, 11, ...
  • {YEAR} - current year at the moment of number generation by numerator => 2018, ...
  • {RANDOM} - random number of Latin characters in uppercase and digits
  • {PREFIX} - specified fixed set of symbols

Document numerators (type DOCUMENT) additionally can use:

  • {CLIENT_ID} - client ID
  • {SELF_ID} - entity ID that is data provider (depends on what is passed to numerator when generating a number)
  • {SELF_COMPANY_ID} - company ID

In CRM (for numerator type CRM_QUOTE, CRM_INVOICE) the following words can be used:

  • {INVOICE_ID} Invoice number
  • {USER_ID_INVOICES_COUNT} - user ID and number of user invoices
  • {QUOTE_ID} - quote number
  • {USER_ID_QUOTES_COUNT} - user ID and number of user quotes

Inside the store (for numerator type ORDER):

  • {USER_ID_ORDERS_COUNT} - user ID and number of user orders
  • {ORDER_ID} - order number

Get all settings for creation of numerator type 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' => 'Numerator 1', 'title' => 'Numerator name', ],
            ['settingName' => 'template', 'type' => 'string', 'title' => 'Number template',],
        ],
        'Bitrix_Main_Numerator_Generator_SequentNumberGenerator' => [
            ['settingName' => 'start', 'type' => 'int', 'default' => 1, 'title' => 'Start sequence number с',],
            ['settingName' => 'step', 'type' => 'int', 'default' => 1, 'title' => 'Increase sequence number for',],
            ['settingName' => 'periodicBy', 'type' => 'array', 'title' => 'Numerator operation period', 'values' => [
                ['settingName' => 'default', 'value' => '', 'title' => 'Continuously',],
                ['settingName' => 'day', 'value' => 'day', 'title' => 'Within a day',],
                ['settingName' => 'month', 'value' => 'month', 'title' => 'Within a month',],
                ['settingName' => 'year', 'value' => 'year', 'title' => 'Within a year',],],
            ],
            ['settingName' => 'timezone', 'type' => 'array', 'values' => [...]],
            ...,
        ],
        ...,
    ],
    'settingsWords' => [
        'Bitrix_Main_Numerator_Generator_SequentNumberGenerator' => ['{NUMBER}' => 'Sequence number',],
        'Bitrix_Main_Numerator_Generator_DateNumberGenerator' => ['{DAY}' => 'Current day', '{MONTH}' => 'Current month', '{YEAR}' => 'Current year',],
        'Bitrix_Main_Numerator_Generator_RandomNumberGenerator' => ['{RANDOM}' => 'Random number',],
        'Bitrix_Main_Numerator_Generator_PrefixNumberGenerator' => ['{PREFIX}' => 'Prefix',],
    ]
];

settingsWords - words for template (Numerator::getTemplateWordsForType('DOCUMENT'))

settingsFields - usually used for formatting the HTML form. Based on settings type, generates code for inputs, dropdown, form fields titles, default values are filled in and etc.

Saving numerator

Finally, saving numerator, setting up and saving the configuration look as follows:

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();

Settings

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

// Bitrix_Main_Numerator_Numerator
Numerator::getType() => [
   [
       'name', // Numerator name - REQUIRED FIELD
       'template' // Number template - REQUIRED FIELD
   ],
],

// Sequence number - {NUMBER}
// Bitrix_Main_Numerator_Generator_SequentNumberGenerator

Generator\SequentNumberGenerator::getType() => [
   [
       'start', // From which number to start
       'step', // Step for increasing number
       'periodicBy', // ['day', 'month', 'year'] - Reset counter at start when starting new period
       'timezone', // What hour zone to use to determine new zone (day and etc.)
                   // ['', 'Pacific/Midway', ...] - values from \CTimeZone::GetZones()
       'isDirectNumeration', // boolean, Use continuous numbering or have independent counters for each company
   ],
],

// Random number from Latin characters in uppercase and digits - {RANDOM}
// Bitrix_Main_Numerator_Generator_RandomNumberGenerator

Generator\RandomNumberGenerator::getType() => [
   [
       'length', // Number length
   ],
],

// Character string - {PREFIX}
// Bitrix_Main_Numerator_Generator_PrefixNumberGenerator

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

// Date - {DAY}, {MONTH}, {YEAR}
// Bitrix_Main_Numerator_Generator_DateNumberGenerator date format presently cannot be configured

Getting existing numerator by ID

use Bitrix\Main\Numerator\Numerator;

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

Getting first existing numerator by its type

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

Getting list of numerators by type

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

Getting next number from numerator

$nextNumber = $numerator->getNext();

Updating numerator settings by 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);

Passing context

Sometimes numerator cannot know with what the service word must be replaced with a template (for example, {INVOICE_ID} - invoice number for numerator in CRM). That is why, some context and data source is required (for numerators that use dynamically configured generators, implementing the interface DynamicConfigurable).

Context can be passed by several methods.

// as second parameter in Numerator::load
\Bitrix\Main\Numerator\Numerator::load($numeratorId, $source = null);

// when having the numerator, to set its context
$numerator->setDynamicConfig($dynamicConfig);

Numerator hash

Numerator containing service word {NUMBER} in the template, can simultaneously respond to several sequence numbers (it will have several "internal counters"). In general, by requesting next number from numerator you will get sequentially increasing 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;

// Get
// 1
// 2
// 3

When hash (string) is specified for numerator and number is queried for different hash - we will get independent counters and will be able to get numbers from each of them separately.

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;

// Get
// 1
// 1
// 2

For example, if to pass company ID as hash you can get independent generation fo sequence numbers in template for various companies using the same single number template.

Hash can be set by several methods.

(For numerators that use generators realizing interface Sequenceable)

use Bitrix\Main\Numerator\Numerator;

// second parameter in Numerator::load as an object
// implementing interface Hashable, returning hash by string in $hashable->getHash()
Numerator::load($numeratorId, $hashable);

// pass hash in getNext as a string
$hash = 'MANAGER_42';
$numerator->getNext($hash)

// set hash using hash setter as an object Hashable
$numerator->setHash($hashable);

© «Bitrix24», 2001-2022
Up