Skip to Content

Номери документів Odoo 19 із префікса, року та лічильника – модуль document_number_prefix_year і пастка за одночасного створення

3 листопада 2026 року | Odoo 19 Community | Власна розробка
3 листопада 2026 р. від
Номери документів Odoo 19 із префікса, року та лічильника – модуль document_number_prefix_year і пастка за одночасного створення

Модуль Odoo 19 document_number_prefix_year: номери документів із префікса, року та лічильника

«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) і кількість розрядів ви задаєте для кожної компанії в меню Налаштування → Нумерація документів.

Структура номера документа AN26000001 із префікса, року та лічильника, з таблицею типів документів

Охоплено пропозиції, замовлення клієнтів, рахунки клієнтів і кредит-ноти, накладні, надходження товарів та замовлення на закупівлю. Префікси на ілюстрації є лише прикладами: 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
  • Лічильник. Найбільший номер знаходить регулярний вираз (^<Stamm>([0-9]{1,15})$, основа екранується) для кожної компанії, включно з назвами без компанії.
  • Рахунки. _set_next_sequence записує назву й викликає _compute_split_sequence, щоб логіка послідовностей Odoo (префікс, номер, визначення року для наступного рахунку журналу) залишалася узгодженою.
  • Налаштування. Поля компанії document_number_* відображаються в res.config.settings. Налаштування відхиляють префікси з пробілом або цифрою в кінці.
  • Переклад. Німецький переклад включено.

Встановлення та налаштування

  1. Покласти теку document_number_prefix_year у шлях addons.
  2. Оновити список застосунків, встановити модуль. Передумовами є Продажі, Закупівлі, Склад і Бухгалтерія.
  3. У меню Налаштування → Нумерація документів внести префікси, формат року та кількість розрядів.
  4. Спершу спробуйте на копії. Номер документа згодом не можна автоматично відкотити, а для рахунків до номера прив’язані обов’язки зберігання та перевірки.

обмеження

Шість обмежень модуля: кошики, формат року, одна серія на компанію, правила префіксів, мало тестів, лише названі документи

  • Пропозиції нумеруються під час створення. Видалені або скасовані пропозиції залишають прогалини. Те саме стосується кожного замовлення клієнта, яке створює інший модуль: кошики вебмагазину (website_sale) — це замовлення зі статусом Пропозиція, і кожне споживає один номер. Без прогалин лише рахунки та кредит-ноти, оскільки вони нумеруються під час проведення.
  • Не змінюйте формат року під час роботи. З основою AN26 модуль читає наявний AN2026000001 як лічильник 26000001. Визначте формат до першого документа.
  • Лічильник щонайбільше 15 розрядів. Довші послідовності цифр після основи ігноруються під час пошуку найбільшого номера.
  • Жодних окремих серій для журналу чи складу. Лічильник діє для кожної компанії, префікса й року. Кілька журналів продажів ділять лічильник рахунків.
  • Префікси не повинні містити пробілу й закінчуватися цифрою, інакше префікс, рік і лічильник більше не вдасться розділити.
  • Опрацьовуються лише названі типи документів.

Тести

Модуль постачається з десятьма автоматичними тестами. Вони перевіряють:

  • Пропозицію та підтвердження: номер пропозиції та замовлення, збереження номера пропозиції
  • Продовження лічильника після імпортованого номера (AN26119 → AN26000120)
  • відсутність наступної перенумерації наявних документів
  • Рахунок, кредит-ноту та зміну року за датою рахунку
  • Замовлення на закупівлю та накладні
  • порожній префікс: стандартний номер Odoo зберігається
  • чотирицифровий рік
  • Префікс зі спеціальними символами
  • кілька номерів в одній транзакції
  • дуже довгі послідовності цифр ігноруються

Виклик:

odoo-bin -d <Testdatenbank> -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. Усі номери в прикладах та на ілюстраціях обрано довільно.