«AN26000001» говорит больше, чем «S00001»: это коммерческое предложение, оно относится к 2026 году и является первым. Многие компании, особенно те, которые переходят на Odoo со старой системы, хотят сохранить свои номера документов именно такими. Сам Odoo нумерует коммерческие предложения, заказы и накладные собственными последовательностями (S00001, WH/OUT/00001, P00001), а счета — префиксом журнала и годом (INV/2026/00001).
Для этого мы написали модуль Document Numbering by Prefix and Year (document_number_prefix_year) для Odoo 19. Он доступен на GitHub как свободное программное обеспечение под лицензией LGPL-3:
github.com/Alex0176/odoo-document-number-prefix-year
Заранее честная оценка: мы не используем этот модуль в Biricon IT Services. Мы публикуем его, потому что он готов, задокументирован и снабжён тестами и может сэкономить чужой труд. Тому, кто его применяет, стоит обратить внимание на разделы Ограничения и Тесты . Рекомендуем прочитать их до начала работы.
Схема нумерации
Каждый номер состоит из трёх частей: префикса для каждого вида документа, года и счётчика с фиксированным числом разрядов. Префикс, формат года (26 или 2026) и число разрядов вы задаёте для каждой компании в разделе Настройки → Нумерация документов.
Обрабатываются коммерческие предложения, заказы клиентов, счета клиентам и кредит-ноты, накладные, поступления товаров и заказы на закупку. Префиксы на иллюстрации — лишь примеры: AN, AU, RE, GU, LI, WE, BE. Если оставить префикс пустым, для этого вида документа сохраняется стандартная нумерация Odoo. Таким образом, модуль ничего не делает, пока вы его не настроите.
Как ведут себя номера
- Каждый год заново. Счётчик с началом нового года снова начинается с 1.
- Продолжение после импортированных номеров. Модуль ищет наибольший существующий номер того же префикса и года, независимо от его длины. Если в базе данных из старой системы есть
AN26119, следующее коммерческое предложение получит номерAN26000120. Именно поэтому модуль подходит для перехода: старые документы импортируются с исходными номерами, а новые документы бесшовно продолжают нумерацию. - Новый номер заказа при подтверждении. Подтверждённое коммерческое предложение при необходимости получает номер из последовательности заказов. Номер коммерческого предложения сохраняется в поле Номер коммерческого предложения в заказе и виден в форме, списке и поиске.
- Счета при проведении. Счета клиентам и кредит-ноты получают номер только при проведении, а не при создании. Поэтому удалённые черновики не оставляют пропусков. Год берётся из даты счёта: счёт от 30.12.2025, проведённый 2.1.2026, называется
RE25…. - Всё остальное остаётся. Счета поставщиков, платежи, проводки и производственные заказы сохраняют стандартные последовательности Odoo. Существующие названия никогда не переписываются, даже если вы снова отключите модуль.
Деликатная часть: два пользователя одновременно
Собственная выдача номеров выглядит просто: найти наибольший номер, прибавить единицу. Но это не так, как только два пользователя в один и тот же момент создают коммерческое предложение. Оба читают «наибольший номер = 0», оба присваивают AN26000001. Для собственных последовательностей Odoo использует последовательности базы данных. У самодельного номера этого нет, а для коммерческих предложений и заказов на закупку в Odoo к тому же нет проверки уникальности по названию: два документа с одинаковым номером просто сохраняются.
Очевидная защита — блокировка. Модуль устанавливает для каждой компании, префикса и года блокировку базы данных (PostgreSQL Advisory Lock), которая удерживается до конца транзакции. Второй пользователь ждёт, пока первый закончит. Но этого недостаточно, и мы обнаружили это экспериментом на копии рабочей базы данных:
Odoo работает с уровнем изоляции REPEATABLE READ. Состояние базы данных, которое видит транзакция, фиксируется при её первом запросе. У пользователя B это состояние уже есть, прежде чем A закончит. Если B после этого ждёт блокировку и получает её, он со своим старым состоянием читает «наибольший номер = 0» и присваивает номер второй раз. Блокировка упорядочила очерёдность, но не обновила знание.
Решение — второе чтение через собственное короткоживущее подключение к базе данных, которое видит все уже подтверждённые строки. Выигрывает большее из двух значений. Первое чтение остаётся необходимым, потому что только оно знает номера, которые та же транзакция уже присвоила, но ещё не подтвердила, например при импорте нескольких документов за один раз.
Мы проверили это на двух транзакциях, в которых вторая заведомо получила своё состояние до коммита первой, а затем ждала блокировку. Без второго чтения оба заказа получили один и тот же номер, с ним — номера 1 и 2.
Важно для оценки: этот эксперимент — ручная проверка. Он не входит в автоматические тесты, потому что для него нужны два настоящих подключения к базе данных, которых тестовая среда Odoo (одна транзакция на тест) не предоставляет.
Техническая реализация
| Документ | Точка подключения |
|---|---|
| Коммерческое предложение | sale.order.create, если название пусто, / или New |
| Заказ клиента | sale.order.action_confirm, перед стандартным подтверждением |
| Счёт, кредит-нота | account.move._set_next_sequence, вызывается при проведении |
| Накладная, поступление товара | stock.picking.create по типу операции |
| Заказ на закупку | purchase.order.create |
- Счётчик. Наибольший номер находит регулярное выражение (
^<основа>([0-9]{1,15})$, основа экранируется) для каждой компании, включая названия без компании. - Счета.
_set_next_sequenceзаписывает название и вызывает_compute_split_sequence, чтобы логика последовательностей Odoo (префикс, номер, определение года для следующего счёта журнала) оставалась согласованной. - Настройки. Поля компании
document_number_*отражаются вres.config.settings. Настройки отклоняют префиксы с пробелом или цифрой в конце. - Перевод. Немецкий перевод включён.
Установка и настройка
- Поместите папку
document_number_prefix_yearв путь addons. - Обновите список приложений, установите модуль. Необходимы Продажи, Закупки, Склад и Бухгалтерия.
- В разделе Настройки → Нумерация документов внесите префиксы, формат года и число разрядов.
- Сначала опробуйте на копии. Номер документа позже нельзя автоматически откатить, а у счетов с номером связаны обязанности хранения и проверки.
Ограничения
- Коммерческие предложения нумеруются при создании. Удалённые или отменённые коммерческие предложения оставляют пропуски. То же относится к любому заказу клиента, создаваемому другим модулем: корзины интернет-магазина (
website_sale) — это заказы в статусе Коммерческое предложение, и каждая расходует по одному номеру. Без пропусков только счета и кредит-ноты, поскольку они нумеруются при проведении. - Не меняйте формат года в ходе работы. С основой
AN26модуль читает существующийAN2026000001как счётчик26000001. Задайте формат до первого документа. - Счётчик не более 15 разрядов. Более длинные последовательности цифр после основы игнорируются при поиске наибольшего номера.
- Нет раздельных серий по журналам или складам. Счётчик действует для каждой компании, префикса и года. Несколько журналов продаж делят счётчик счетов.
- Префиксы не должны содержать пробела и не должны оканчиваться цифрой, иначе префикс, год и счётчик невозможно будет разделить.
- Обрабатываются только перечисленные виды документов.
Тесты
В комплект модуля входят десять автоматических тестов. Они проверяют:
- Коммерческое предложение и подтверждение: номер коммерческого предложения и номер заказа, сохранение номера коммерческого предложения
- Продолжение счёта после импортированного номера (
AN26119→AN26000120) - отсутствие последующей перенумерации существующих документов
- Счёт, кредит-нота и смена года по дате счёта
- Заказ на закупку и накладные
- пустой префикс: стандартный номер Odoo сохраняется
- четырёхзначный год
- Префикс со специальными символами
- несколько номеров в одной транзакции
- очень длинные последовательности цифр игнорируются
Вызов:
odoo-bin -d <тестовая_база> -i document_number_prefix_year --test-enable --test-tags=/document_number_prefix_year --stop-after-init
Тесты выполняются в обычных транзакциях. Поведение при одновременном создании двумя пользователями в них не входит, оно было проверено вручную на копии базы данных, как описано выше. Тому, кто применяет модуль в системе со множеством одновременно работающих пользователей, следует повторить этот эксперимент на собственной базе данных.
Юридическое примечание о номере счёта
Согласно § 11 UStG счета должны содержать последовательный номер, присваиваемый однократно для идентификации счёта. Модуль нумерует счета при проведении и с собственным счётчиком для каждого префикса и года, что этому соответствует. Отвечает ли ваша конкретная настройка (несколько журналов, кредит-ноты с собственным префиксом, смена года) требованиям вашего налогового консультанта, вам нужно выяснить с ним. Эта статья не является юридической консультацией.
Часто задаваемые вопросы
Почему просто не изменить последовательности Odoo?
Для счетов это возможно через префикс журнала. Но для коммерческих предложений, заказов, накладных и заказов на закупку нет общей схемы из префикса, года и счётчика со сменой года, а счётчик не знает об импортированных старых номерах. Именно здесь применяется модуль.
Перезаписывается ли существующая нумерация?
Нет. Модуль присваивает только новые номера. Уже сохранённые названия остаются неизменными, в том числе при отключении.
Как снова отключить его?
Очистите префикс вида документа. Тогда Odoo снова будет нумеровать его самостоятельно. Удаление модуля также не меняет присвоенные номера.
Используете ли вы его сами?
Нет. У нас работают стандартные номера Odoo. Мы проверили модуль автоматическими тестами и описанным ручным экспериментом, но не в действующей системе со множеством пользователей.
Работает ли он с Odoo 17 или 18?
Мы тестировали его только с Odoo 19.0 Community. Для других версий он может подойти или нет, мы это не проверяли.
Под какой лицензией он распространяется?
Под LGPL-3. Сообщения об ошибках и улучшения приветствуются в виде issue в репозитории GitHub .
Поддержка от Biricon IT Services
Мы обслуживаем установки Odoo для малых и средних предприятий: от внедрения через доработки и миграции до постоянной эксплуатации. Если вы хотите сохранить свои номера документов при переходе, проверить выдачу номеров под нагрузкой или безопасно внедрить подобный модуль в рабочий экземпляр, мы охотно поможем. Другие наши собственные разработки: Firmenbuch и проверка адресов для австрийских клиентов, Наборы продуктов в коммерческом предложении как раздел и Web RBL — чёрный список для вредоносного трафика.
По состоянию на 3 ноября 2026 г. Версия модуля 19.0.1.0.0. Все номера в примерах и на иллюстрациях выбраны произвольно.