„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. Той е свободен софтуер под лиценза LGPL-3 в GitHub:
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“ и присвоява номера втори път. Ключалката е уредила реда, но не е обновила знанието.
Решението е второ четене през собствен, краткотраен достъп до базата данни, който вижда всички вече потвърдени редове. По-голямата от двете стойности печели. Първото четене остава необходимо, защото само то знае номерата, които същата транзакция вече е присвоила, но още не е потвърдила, например при импорт на няколко документа наведнъж.
Проверихме това с две транзакции, при които втората доказуемо е взела своето състояние преди commit на първата и после е изчакала ключалката. Без второто четене двете поръчки получиха един и същ номер, с него – номерата 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. Настройките отхвърлят префикси с интервал или с цифра накрая. - Превод. Включен е немски превод.
Инсталиране и настройка
- Поставете папката
document_number_prefix_yearв пътя на addons. - Обновете списъка с приложения, инсталирайте модула. Изисквания са Продажби, Покупки, Склад и Счетоводство.
- В Настройки → Номериране на документи въведете префикси, формат на годината и брой цифри.
- Първо опитайте върху копие. Номерът на документ не може по-късно да бъде върнат автоматично, а при фактурите към номера са свързани задължения за съхранение и проверка.
ограниченията
- Офертите се номерират при създаването. Изтрити или анулирани оферти оставят празнини. Същото важи за всяка поръчка на клиент, която създава друг модул: кошниците на уебмагазина (
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 за малки и средни предприятия: от внедряването през адаптациите и миграциите до текущата експлоатация. Ако искате при преминаването да запазите номерата на документите си, да проверите присвояването на номера под натоварване или да въведете безопасно модул като този във вашата продуктивна инстанция, с удоволствие ще помогнем. Още собствени разработки: Търговски регистър и проверка на адреси за австрийски клиенти, Продуктови комплекти в офертата като раздел и Web RBL, списъкът за блокиране на трафик от атаки.
Към: 3 ноември 2026 г. Версия на модула 19.0.1.0.0. Всички номера в примерите и изображенията са произволно избрани.