Odoo 19 removed picking-level accounting, interim accounts, and Stock Valuation Layers (SVL). This creates serious problems for Bulgarian companies - violation of BG NAS 2, lack of audit trail, and historical cost issues. BL Consulting developed two modules that restore proper behavior, adapted to Odoo 19's new architecture.
Recap: The Problem
In our previous article, we examined the fundamental issue with Odoo 19: removal of stock.valuation.layer, interim accounts (Stock Input/Output), and shifting all accounting to the invoice level.
In brief:
- Historical cost gets overwritten by the invoice price — violating the historical cost principle (IAS 2 / BG NAS 2).
- Audit trail disappears — there's no longer a document linking physical movement to accounting entries.
- Auditors expect Dr. 302 / Cr. 301 at goods receipt, not at invoice posting.
This is blocking for any Bulgarian company subject to audit. Therefore, BL Consulting developed two modules that restore proper behavior — but adapted to Odoo 19's new architecture.
The Solution: Two Modules
1. l10n_bg_stock_account — picking-level accounting
Repository: rosenvladimirov/l10n-bulgaria/tree/19.0/l10n_bg_stock_account
License: LGPL-3 (OCA l10n-bulgaria)
Version: 19.0
The module generates journal entries at picking validation — as expected by Bulgarian accounting legislation.
2. l10n_bg_stock_price_diff — MO chain price difference (Enterprise)
Repository: rosenvladimirov/l10n-bulgaria-ee/tree/19.0/l10n_bg_stock_price_diff
License: OPL-1
Version: 19.0.1.0.1
An extension that solves the secondary problem: what happens when the invoice price differs from the PO price, and the raw material has already been consumed in production with finished goods partially sold.
How l10n_bg_stock_account Works
V19 Adaptation: Direct stock.move Integration
Since Odoo 19 removed stock.valuation.layer, the module has been rewritten to read valuation fields directly from stock.move — remaining_qty, value, and the new valuation fields that replaced SVL.
This is not a simple backport of the old V18 module. The data model is different and the journal item creation logic has been rewritten.
Example: Goods Receipt
Scenario: Vendor delivers 100 pcs of raw material at 10 BGN/pc (PO value 1000 BGN).
Standard Odoo 19 behavior: no entry until invoice posting.
With l10n_bg_stock_account — at picking validation:
Dr. 302 Materials 1000.00
Cr. 301 Goods Received Not
Invoiced (GRNI) 1000.00
After receiving invoice (PO=Invoice):
Dr. 301 GRNI 1000.00
Cr. 401 Accounts Payable 1000.00
Result: The valuation account is hit at physical receipt, as the auditor expects. The GRNI account serves as a clearing account between receipt and invoice.
How l10n_bg_stock_price_diff Works
This is a separate Enterprise module for the more complex scenario: price differences in manufacturing.
The Algorithm: Recursive MO Chain Traversal
At vendor bill _post(), the module:
- Detects differences between PO and Invoice for each line.
- Recursively traverses the MO chain — from raw material down to finished goods, with maximum depth of 10 levels.
- For each quantity, tracks destiny — whether it's in warehouse, in WIP, in FG, or in COGS.
- Creates ONE journal entry with proportional distribution.
Three New Models
| Model | Role |
|---|---|
l10n.bg.price.diff
|
Document with sequence (analog to Price Variance document) |
l10n.bg.price.diff.line
|
PO↔Invoice difference for specific receipt move |
l10n.bg.price.diff.correction
|
Recursive correction tree with depth and destiny tracking |
Why This Matters for Bulgarian Context
BG NAS 2 Compliance
BG NAS 2 (and IAS 2) require stock to be valued in real time, with movements creating accounting entries at physical movement. Without l10n_bg_stock_account, Odoo 19 doesn't meet this requirement.
Auditor Expectations
Every Bulgarian auditor will ask: "Show me the Dr. 302 / Cr. 301 entry from the receipt date." If no such entry exists — questions follow. The module closes this expectation without manual corrections.
Manufacturing Companies
For MRP Design Matrix pilot clients (canning factory, bags, security doors, roller shutters) — all with active production — l10n_bg_stock_price_diff is mandatory. Without it, COGS values will systematically differ from actual costs with every PO↔Invoice difference.
Installation and Configuration
Repositories
Community module:
Repository: rosenvladimirov/l10n-bulgaria (19.0 branch)
Module: l10n_bg_stock_account
Enterprise module:
Repository: rosenvladimirov/l10n-bulgaria-ee (19.0 branch)
Module: l10n_bg_stock_price_diff
Conclusion
Odoo 19 made architectural simplifications that work for simple trading companies but violate basic requirements for manufacturing firms and any business under audit. l10n_bg_stock_account and l10n_bg_stock_price_diff restore correct behavior — not by working against V19's new architecture, but by cleanly integrating with the new stock.move-based valuation model.
If you have a manufacturing company or are under audit — these two modules are not optional.
OCA maintainer l10n-bulgaria · 10+ years of Odoo implementations · bl-consulting.net