BambooForge Labs

Stock Valuation History & Ledger Reconciliation

Opening, in, out and closing stock value per account for a period, next to the ledger - read on the accounting date, so both answer one question.

Buy on the Odoo Apps StoreOpen the live demoAccounting€199Community & Enterprise

Available for Odoo 16.0, Odoo 17.0, Odoo 18.0. Technical name bambooforge_valuation_history.

Odoo 16.0Odoo 17.0Odoo 18.0
Screens and walkthrough for
Transcript of the walkthrough (Odoo 18)

Stock Valuation History & Ledger Reconciliation. Opening, in, out and closing stock value per account for a period, next to the ledger - read on the accounting date, so both answer one question. At every closing somebody asks the same question: the stock account says one number, inventory says another, where is the difference. Odoo Community can list the valuation layers and filter them to a date, and from there the answer gets assembled by hand in a spreadsheet.

In the next few minutes: stock valuation history & ledger reconciliation, then both sides on the accounting date, then opening, in, out, closing, then against the ledger, then what does not fit is named, not hidden. Then what this app deliberately does not do, so you can tell before you buy whether it fits. Everything lives under Stock Valuation History. Stock Valuation History & Ledger Reconciliation.

At every closing somebody asks the same question: the stock account says one number, inventory says another, where is the difference. Odoo Community can list the valuation layers and filter them to a date, and from there the answer gets assembled by hand in a spreadsheet. This is that answer as a report — and it is built on one correction that matters more than the layout. Both sides on the accounting date.

A valuation layer has no date of its own. Odoo's layer list groups by Date, and that field is create_date — the moment the row was written to the database. The journal entry the layer produced carries an accounting date, and that is what the trial balance is built from. Most of the time they are the same day and nobody notices.

Then somebody receives goods on the 2nd of January against December, or an entry is reset to draft and re-posted into the prior period, and the two dates part company. From then on the layer report and the balance sheet disagree, by exactly that amount, and neither of them says why. Opening, in, out, closing. Pick a period.

For every stock valuation account you get: ============ =================================================== Opening everything valued before the start of the period In positive value in the period — receipts, revaluations up Out negative value in the period — deliveries, scrap, write-downs Closing opening + in − out ============ =================================================== Against the ledger. Next to Closing sits In the Ledger — the posted balance of that same account on the same date — and the difference between them. the valuation layers that were added up to make the stock column, filtered by the same dates and the same accounting-date rule; the journal items that were added up to make the ledger column, posted only, on or before the closing date. Every account a category values stock on appears, whether or not anything moved through it, and so does any account that stock entries once reached but no category names today — the balance left behind when a chart is renumbered or a category is pointed at a new account.

Comparing only the accounts inventory reached this period is how a report announces that the books agree while a whole balance sits unexplained beside it. What does not fit is named, not hidden. Two kinds of value cannot belong to a reconciled line, and both are reported as their own explanation rather than quietly dropped: Value with no account. A category set to automated valuation that names no valuation account still produces layers, and that value belongs to no account at all.

The fix is the category. Value with no posted entry. A layer whose journal entry is still in draft — or was never created — counts as stock and counts for nobody in the ledger. Whenever there is a difference, this is usually most of it.

Dropping either would make the report balance while the stock did not, which is worse than having no report. Filtering, and what a filtered run may claim. You can narrow the run to a few product categories. That narrows the stock side only — the ledger side is whole accounts, and there is no honest way to take a slice of an account balance by product category.

So a filtered run is a movement report, not a reconciliation, and it says so: the difference column is left out rather than filled with the difference between part of the inventory and all of an account. Who can run it. The module carries its own group, Stock Valuation History, in the Accounting category, and it implies Odoo's read-only accounting group. This is deliberate.

account.group_account_readonly lives in Odoo's hidden module category, so on a Community database running Invoicing only it cannot be ticked for anybody. Had the menu been anchored to it, the only way an administrator could let an accountant read this report would be to grant them write access to something else. Now it is a tick-box, and the report writes nothing anywhere. Series.

There is no 19.0 version, on purpose. Odoo 18.0 added this to Community itself — stock_value() next to stock_accounting_value(), grouped by account, with a date — and shipping a paid module that duplicates it would mean selling something given away, and disagreeing with the core report the first time the two rounded differently. On 19.0 the right answer is the one already in the box. The complete manual is at docs dot bambooforge dot dev, the demo database is linked from the store page, and support answers within twenty-four hours.

Links are in the description.

Backdated - bambooforge_valuation_history
Backdated
Drill - bambooforge_valuation_history
Drill
Movement - bambooforge_valuation_history
Movement
Reconcile - bambooforge_valuation_history
Reconcile

Key facts

What it is
Opening, in, out and closing stock value per account for a period, next to the ledger - read on the accounting date, so both answer one question.
For
Accounting
Odoo versions
16.0, 17.0, 18.0 - Community and Enterprise
Runs on
Odoo.sh or Odoo you host yourself - not Odoo Online, which accepts no third-party apps
Price
199 EUR, one-time, on the Odoo Apps Store
Technical name
bambooforge_valuation_history
Manual
https://docs.bambooforge.dev/bambooforge_valuation_history/
Live demo
https://demo18.bambooforge.dev/odoo/action-bambooforge_valuation_history.action_bf_stock_value_run
Store page
https://apps.odoo.com/apps/modules/18.0/bambooforge_valuation_history
Manual last updated
2026-09-06

Stock Valuation History & Ledger Reconciliation

At every closing somebody asks the same question: the stock account says one number, inventory says another, where is the difference. Odoo Community can list the valuation layers and filter them to a date, and from there the answer gets assembled by hand in a spreadsheet.

This is that answer as a report — and it is built on one correction that matters more than the layout.

Both sides on the accounting date

A valuation layer has no date of its own. Odoo's layer list groups by Date, and that field is create_date — the moment the row was written to the database. The journal entry the layer produced carries an accounting date, and that is what the trial balance is built from.

Most of the time they are the same day and nobody notices. Then somebody receives goods on the 2nd of January against December, or an entry is reset to draft and re-posted into the prior period, and the two dates part company. From then on the layer report and the balance sheet disagree, by exactly that amount, and neither of them says why.

This report places every layer on the date of the journal entry it produced. A layer that never produced one is placed on the day it was written — and still counted, because a value that reached no entry is precisely the sort of difference the report exists to surface.

Opening, in, out, closing

Pick a period. For every stock valuation account you get:

Opening

everything valued before the start of the period

In

positive value in the period — receipts, revaluations up

Out

negative value in the period — deliveries, scrap, write-downs

Closing

opening + in − out

Closing is never stored. It is its own parts added together, every time the report runs, because a stored total is one more number that can end up disagreeing with the numbers under it.

So a change in the stock value is explained rather than only observed: the balance moved by €40,000, of which €52,000 came in and €12,000 went out.

Against the ledger

Next to Closing sits In the Ledger — the posted balance of that same account on the same date — and the difference between them.

Every account a category values stock on appears, whether or not anything moved through it, and so does any account that stock entries once reached but no category names today — the balance left behind when a chart is renumbered or a category is pointed at a new account. Comparing only the accounts inventory reached this period is how a report announces that the books agree while a whole balance sits unexplained beside it.

Two buttons on every line open what is behind each figure:

  • the valuation layers that were added up to make the stock column, filtered by the same dates and the same accounting-date rule;

  • the journal items that were added up to make the ledger column, posted only, on or before the closing date.

The filters are the report's own, not an approximation of them, so the two lists always add up to the two numbers they came from. A difference becomes something to click on rather than something to go hunting for.

What does not fit is named, not hidden

Two kinds of value cannot belong to a reconciled line, and both are reported as their own explanation rather than quietly dropped:

  • Manually valued stock. A product category on manual (periodic) valuation still produces valuation layers, and Odoo posts no journal entries for them — core actually clears the valuation account of any category that is not automated. There is nothing to reconcile that value against, so it is reported as its own total and left out of the comparison. It is a supported way to run Odoo, not a fault, and this report does not tell you to change your accounting policy to suit it.

  • Value with no account. A category set to automated valuation that names no valuation account still produces layers, and that value belongs to no account at all. The fix is the category.

  • Value with no posted entry. A layer whose journal entry is still in draft — or was never created — counts as stock and counts for nobody in the ledger. Whenever there is a difference, this is usually most of it.

Dropping either would make the report balance while the stock did not, which is worse than having no report.

Filtering, and what a filtered run may claim

You can narrow the run to a few product categories. That narrows the stock side only — the ledger side is whole accounts, and there is no honest way to take a slice of an account balance by product category.

So a filtered run is a movement report, not a reconciliation, and it says so: the difference column is left out rather than filled with the difference between part of the inventory and all of an account.

Who can run it

The module carries its own group, Stock Valuation History, in the Accounting category, and it implies Odoo's read-only accounting group.

This is deliberate. account.group_account_readonly lives in Odoo's hidden module category, so on a Community database running Invoicing only it cannot be ticked for anybody. Had the menu been anchored to it, the only way an administrator could let an accountant read this report would be to grant them write access to something else. Now it is a tick-box, and the report writes nothing anywhere.

Series

Community 16.0, 17.0 and 18.0.

There is no 19.0 version, on purpose. Odoo 18.0 added this to Community itself — stock_value() next to stock_accounting_value(), grouped by account, with a date — and shipping a paid module that duplicates it would mean selling something given away, and disagreeing with the core report the first time the two rounded differently. On 19.0 the right answer is the one already in the box.

How we make sure it works

Before every release, 28 automated checks run against this app on Odoo 16, 17 and 18. Among them:

  • A reader cannot report on another company.

  • Running twice does not double the lines.

  • The notes stay shut when there is nothing to note.

  • Two wrong accounts that cancel out are not agreement.

  • Manual valuation is not called a misconfiguration.

The complete list is in the source you receive.

Install

  1. Copy bambooforge_valuation_history into your addons path and update the app list, or install the ZIP from the Odoo Apps Store.

  2. Install Stock Valuation History & Ledger Reconciliation.

  3. Open Stock Valuation History.

Questions people ask

Which Odoo versions does it run on?

Odoo 16.0, 17.0, 18.0, on the series you buy it for; each series is its own listing.

Community or Enterprise?

Both. It needs no Enterprise app.

What does it need?

The standard Inventory Valuation app. No extra Python package.

Where does it show up?

Under the Stock Valuation History menu.

Does anything leave my server?

No. It makes no call outside your Odoo server: no telemetry, no licence check, no third-party service.

What happens if I uninstall it?

Odoo drops the app's own tables and fields; the standard records it worked on (contacts, orders, products) stay as they are.