Skip to content

Conversation

@lugr-odoo
Copy link
Contributor

@lugr-odoo lugr-odoo commented Oct 17, 2025

A neo–business-memento for the new stock valuation system in Odoo 19.0, hastily adapted from the extant ones in odoo/functional-mementoes that were written in ES5 with a mixture of (now legacy) React.DOM, jQuery and manual DOM manipulation with hardcoded display data for Odoo 8.0 and mostly unchanged since then. Its only other remnant in contemporary documentation is the accounting cheat sheet. Ideally, both cheat sheets should be rewritten with modern libraries in a way that meshes better with the rest of our documentation pipeline (eg without hardcoded data, with minimal tampering of raw HTML on top of Sphinx).

The old documentation (the 'Automatic inventory valuation' and 'Using inventory valuation' pages) was deleted to make way for it and the links pointing at it were snipped or rewritten. The 'inventory valuation' section was raised by one level in the hierarchy.

Until further documentation is written and the existing stock valuation documentation is adapted, this cheat sheet and the OXP 2025 stock talk (latter half) can be used as a reference.

Task ID: 5107300

@robodoo
Copy link
Collaborator

robodoo commented Oct 17, 2025

Pull request status dashboard

@lugr-odoo lugr-odoo force-pushed the 19.0-inventory_valuation_cheatsheet-lugr branch 5 times, most recently from 8a12b20 to 3966c78 Compare October 20, 2025 16:27
@Felicious
Copy link
Contributor

Hi @lugr-odoo! Since this project was primarily handled by the POs and FP, I won’t dispute the design or readability choices made here. I do have a couple of questions though:

  • The Inventory valuation folder was originally nested under Product management. In your PR, it now appears on its own at the bottom of the Inventory documentation landing page, which makes it a bit harder to locate. Was the intention behind this move to make the section easier to find in the navigation?
  • Would it be possible to move the interactive tables into a tab below the text block, like in this other article? The current layout makes the tables quite dominant, and makes it harder to follow the main content. Additionally, placing them beside the content makes the page incompatible with mobile viewing, and removing the top-right page navigational links to make space disrupts the page’s hierarchy and makes it harder to jump between key sections.
  • When do you anticipate having capacity to explore more modern approaches for displaying table data? In a future iteration aimed at improving readability and user learning, would it be possible for the inventory and accounting writing teams to provide input on how the information might be best presented?

Approving this now to support the launch timeline. Our team would, however, like to revisit this soon to make revisions aimed at improving readability! (:

@dalaOdoo
Copy link
Contributor

@Felicious we can discuss these on discord.
At the moment we are in a hurry to publish this asap.

cc @lugr-odoo

@lugr-odoo lugr-odoo force-pushed the 19.0-inventory_valuation_cheatsheet-lugr branch 8 times, most recently from a5bd224 to 65712f8 Compare October 21, 2025 14:14
@lugr-odoo lugr-odoo marked this pull request as ready for review October 21, 2025 14:20
@C3POdoo C3POdoo requested review from a team October 21, 2025 14:21
@lugr-odoo lugr-odoo force-pushed the 19.0-inventory_valuation_cheatsheet-lugr branch from 65712f8 to 85fb613 Compare October 21, 2025 14:31
@lugr-odoo
Copy link
Contributor Author

Marking back as draft for a last second change to remove the (now outdated) inventory valuation pages and clean up the anchors leading up to them.

@lugr-odoo lugr-odoo marked this pull request as draft October 21, 2025 15:21
@AntoineVDV AntoineVDV removed the request for review from a team October 21, 2025 15:25
@lugr-odoo lugr-odoo force-pushed the 19.0-inventory_valuation_cheatsheet-lugr branch 4 times, most recently from e5f7d30 to ce6e1d6 Compare October 22, 2025 07:56
@lugr-odoo lugr-odoo marked this pull request as ready for review October 22, 2025 08:16
@C3POdoo C3POdoo requested a review from a team October 22, 2025 08:19
@dalaOdoo
Copy link
Contributor

@Felicious @dade-odoo we know this is a big PR but we need it asap

Copy link
Contributor

@Felicious Felicious left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Appreciate your herculean effort with this cheat sheet, @lugr-odoo, @dalaOdoo, and @crl-odoo!

I've made minor wording suggestions in my review for the Inventory sections (I'll let Dallas handle the Accounting ones!). Feel free to apply the ones that make sense!

As for the redirect links, can you please edit the 19.0.txt to redirect the "Using inventory valuation" and "Automatic inventory valuation" pages to this cheat sheet? Maybe I missed it in the files changed, but I didn't see this.

.. important::
This documentation is for Odoo 19 or later.
:ref:`Discover why we changed. <changes-in-19>`

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

extra line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sections must be separated by two empty lines.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh okay! definitely ignore my suggestion since it won't render properly (:

Comment on lines 156 to 157
value in real time as you **receive and deliver goods**. The reporting menu allows analysing
inventory on hand and values per company, location, product, etc.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
value in real time as you **receive and deliver goods**. The reporting menu allows analysing
inventory on hand and values per company, location, product, etc.
value in real time as you **receive and deliver goods**. The reporting menu lets you analyze
inventory quantities and values by company, location, product, and more.

Comment on lines 144 to 147
.. note:: Removal strategies also support :abbr:`LIFO (Last In, First Out)` and
:abbr:`FEFO (First Expiry, First Out)`, but they only impact which product is first picked, not
the valuation method. For example, you can pick using LIFO, but using Average Cost for valuation,
as LIFO is not allowed by :abbr:`IFRS (International Financial Reporting Standards)`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.. note:: Removal strategies also support :abbr:`LIFO (Last In, First Out)` and
:abbr:`FEFO (First Expiry, First Out)`, but they only impact which product is first picked, not
the valuation method. For example, you can pick using LIFO, but using Average Cost for valuation,
as LIFO is not allowed by :abbr:`IFRS (International Financial Reporting Standards)`.
.. note::
Removal strategies like :abbr:`LIFO (Last In, First Out)` and :abbr:`FEFO (First Expiry, First
Out)` determine which product is picked first, not how inventory is valued. For example, you can
pick using :abbr:`LIFO (Last In, First Out)`, but inventory is valued with Average Cost, since
:abbr:`LIFO (Last In, First Out)` valuation isn't permitted under :abbr:`IFRS (International
Financial Reporting Standards)`.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mixed indentation breaks the text out of the note box and triggers the warning WARNING: Explicit markup ends without a blank line; unexpected unindent.

You can click on :guilabel:`Unit Cost` to check all existing updates and their origins. In
:abbr:`AVCO (Average Cost)` this allows you to understand how the currently used value was
calculated.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
You can click on :guilabel:`Unit Cost` to check all existing updates and their origins. In
:abbr:`AVCO (Average Cost)` this allows you to understand how the currently used value was
calculated.
On the *Stock* report, click any row item in the :guilabel:`Unit Cost` column to view all stock moves (such as receipts or inventory adjustments) that affect valuation and their sources. This is useful for
:abbr:`AVCO (Average Cost)` to see how the average cost is calculated.

Comment on lines 377 to 381
By opening :guilabel:`Total Value`, you can see all incoming quantities for which you still have a
remaining quantity and the value used for their valuation. In AVCO or standard cost, the used value
is always the current average unit cost. In FIFO, remaining units from each previous incoming move
keep their own individual valuation.

In FIFO or AVCO remaining quantities from a previous incoming move can have their value adjusted if
necessary.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
By opening :guilabel:`Total Value`, you can see all incoming quantities for which you still have a
remaining quantity and the value used for their valuation. In AVCO or standard cost, the used value
is always the current average unit cost. In FIFO, remaining units from each previous incoming move
keep their own individual valuation.
In FIFO or AVCO remaining quantities from a previous incoming move can have their value adjusted if
necessary.
The :guilabel:`Total Value` represents the cost of remaining stock, along with the value used for their valuation
- In AVCO or standard cost, the total value is always the current average unit cost
- In FIFO, remaining units from each incoming move retain their original valuation
In FIFO or AVCO, the value of remaining quantities from earlier moves can have their value adjusted if
necessary.

@lugr-odoo lugr-odoo force-pushed the 19.0-inventory_valuation_cheatsheet-lugr branch 3 times, most recently from 91ac8b5 to cfb5e89 Compare October 22, 2025 20:49
@lugr-odoo
Copy link
Contributor Author

I have added the redirects and converted the footnote links into a plain-text numbered list, but the suggested changes to the content itself are too drastic for me to tack on at the last second without consulting the POs. Further changes can always be done in later PRs following coordinated deliberation.

@Felicious
Copy link
Contributor

Sounds good, @lugr-odoo ! I didn't realize the content suggestions would be a blocker; I can always bring them up again in the next iteration (: Appreciate your hard work on this!

Copy link
Contributor

@dade-odoo dade-odoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @lugr-odoo , thank you for your work on this! I've limited my review to just the more important aspects for now and we can improve it further once it's merged. Let me know if you have any questions 🙏
cc @dalaOdoo @crl-odoo @Felicious

Comment on lines 10 to 13

.. important::
This documentation is for Odoo 19 or later.
:ref:`Discover why we changed. <changes-in-19>`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.. important::
This documentation is for Odoo 19 or later.
:ref:`Discover why we changed. <changes-in-19>`

Comment on lines 413 to 455

.. _changes-in-19:

Changes in Odoo 19
==================

Before Odoo 19, the Perpetual accounting method was implemented by posting real-time accounting
entries at each stock movement. That created a lot of journal items in accounting, which was an
issue for performance, general ledger clarity and auditability.

Since Odoo 19, the Perpetual method impacts the stock valuation account at the invoice level. The
closing entry is then used to manage bills to receive, invoices to issue, deferred revenues, prepaid
expenses, and other gaps between inventory values and accounting ones.

.. h:div:: feature-table doc-aside
+-----------------------+--------------------------------+--------------------------------+
| | Odoo 18 | Odoo 19 |
+=======================+================================+================================+
| Periodic Continental | :meh:`Manual closing` | :good:`Automated closing` |
+-----------------------+--------------------------------+--------------------------------+
| Periodic Anglo-Saxon | :bad:`Not supported` | :good:`Fully supported` |
+-----------------------+--------------------------------+--------------------------------+
| Perpetual Continental | :meh:`Manual closing` | :good:`` |
+-----------------------+--------------------------------+--------------------------------+
| Perpetual Anglo-Saxon | :meh:`Manual closing` | :good:`` |
+-----------------------+--------------------------------+--------------------------------+
| Accounting valuation | :meh:`Requires inventory` | :good:`Accounting only` |
+-----------------------+--------------------------------+--------------------------------+
| Perpetual Entries | :good:`Invoices + every moves` | :good:`Invoices + one closing` |
+-----------------------+--------------------------------+--------------------------------+
| Invoices to issue | :bad:`` | :good:`` |
+-----------------------+--------------------------------+--------------------------------+
| Prepaid expenses | :bad:`` | :good:`` |
+-----------------------+--------------------------------+--------------------------------+
| Bills to receive | :bad:`` | :good:`` |
+-----------------------+--------------------------------+--------------------------------+
| Deferred revenues | :bad:`` | :good:`` |
+-----------------------+--------------------------------+--------------------------------+
| Performance | :bad:`Slower` | :good:`Faster` |
+-----------------------+--------------------------------+--------------------------------+
| General ledger | :good:`More journal entries` | :good:`Fewer journal entries` |
+-----------------------+--------------------------------+--------------------------------+
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.. _changes-in-19:
Changes in Odoo 19
==================
Before Odoo 19, the Perpetual accounting method was implemented by posting real-time accounting
entries at each stock movement. That created a lot of journal items in accounting, which was an
issue for performance, general ledger clarity and auditability.
Since Odoo 19, the Perpetual method impacts the stock valuation account at the invoice level. The
closing entry is then used to manage bills to receive, invoices to issue, deferred revenues, prepaid
expenses, and other gaps between inventory values and accounting ones.
.. h:div:: feature-table doc-aside
+-----------------------+--------------------------------+--------------------------------+
| | Odoo 18 | Odoo 19 |
+=======================+================================+================================+
| Periodic Continental | :meh:`Manual closing` | :good:`Automated closing` |
+-----------------------+--------------------------------+--------------------------------+
| Periodic Anglo-Saxon | :bad:`Not supported` | :good:`Fully supported` |
+-----------------------+--------------------------------+--------------------------------+
| Perpetual Continental | :meh:`Manual closing` | :good:`✓` |
+-----------------------+--------------------------------+--------------------------------+
| Perpetual Anglo-Saxon | :meh:`Manual closing` | :good:`✓` |
+-----------------------+--------------------------------+--------------------------------+
| Accounting valuation | :meh:`Requires inventory` | :good:`Accounting only` |
+-----------------------+--------------------------------+--------------------------------+
| Perpetual Entries | :good:`Invoices + every moves` | :good:`Invoices + one closing` |
+-----------------------+--------------------------------+--------------------------------+
| Invoices to issue | :bad:`✗` | :good:`✓` |
+-----------------------+--------------------------------+--------------------------------+
| Prepaid expenses | :bad:`✗` | :good:`✓` |
+-----------------------+--------------------------------+--------------------------------+
| Bills to receive | :bad:`✗` | :good:`✓` |
+-----------------------+--------------------------------+--------------------------------+
| Deferred revenues | :bad:`✗` | :good:`✓` |
+-----------------------+--------------------------------+--------------------------------+
| Performance | :bad:`Slower` | :good:`Faster` |
+-----------------------+--------------------------------+--------------------------------+
| General ledger | :good:`More journal entries` | :good:`Fewer journal entries` |
+-----------------------+--------------------------------+--------------------------------+

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to keep this info, we can add it in a blog post and link to the blog post or to the OXP video, but it's not necessary in the documentation.

Comment on lines 382 to 384

.. image:: cheat_sheet/total-value.png
:scale: 90%
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.. image:: cheat_sheet/total-value.png
:scale: 90%

Instead of showing how to adjust the valuation with a screenshot, let's explain it. This way we won't have to worry about any issues with the image loading, the image not being translated to other languages, or the information not being understood by LLMs that crawl the page. I suggest adding to the end of Felicia's edit:

necessary: Click on the product's :guilabel:Total Value, then select the incoming moves to be
adjusted, click :icon:fa-cog :guilabel:Actions, and then :guilabel:Adjust Valuation. Enter
the new :guilabel:Value and, optionally, a :guilabel:Description.

In Accounting
-------------

Open :menuselection:`Review --> Inventory Valuation` to have a look at the difference between the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Open :menuselection:`Review --> Inventory Valuation` to have a look at the difference between the
Open :menuselection:`Accounting --> Review --> Inventory Valuation` to see the difference between the

accounting stock value and the current inventory value recorded thanks to the incoming moves with a
remaining quantity.

Click on :guilabel:`Generate Entry` to get a new accounting entry to review and post.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Click on :guilabel:`Generate Entry` to get a new accounting entry to review and post.
Click on :guilabel:`Generate Entry` to generate a new accounting entry to review and post.

Comment on lines 400 to 402
Open
:menuselection:`Review --> Invoices not received, Invoices to be issued, Prepaid expenses and Deferred Revenues`
to easily record these entries.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this menu item? I don't see it under the Review menu.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will arrive soon ...

There are two accounting practices on how to maintain your accounts:

**Periodic:** Post vendor bills as expenses by nature, and update stock valuation in the closing
entry by reducing expenses (stock variation). It’s the best practice in Europe.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
entry by reducing expenses (stock variation). It’s the best practice in Europe.
entry by reducing expenses (stock variation). This is the best practice in Europe.

entry by reducing expenses (stock variation). It’s the best practice in Europe.

**Perpetual:** Post vendor bills as assets (stock valuation), report expenses when goods are sold
(cost of goods sold). It’s the best practice in countries that follow Anglo-Saxon accounting, like
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(cost of goods sold). It’s the best practice in countries that follow Anglo-Saxon accounting, like
(cost of goods sold). This is the best practice in countries that follow Anglo-Saxon accounting, like

to easily record these entries.

With Anglo-Saxon perpetual accounting, this will also help to distribute recorded Inventory
Variations to accounts such as Bill to Receive/:abbr:`GRNI (Goods Received Not Invoiced)` or
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Variations to accounts such as Bill to Receive/:abbr:`GRNI (Goods Received Not Invoiced)` or
Variations to accounts such as Bills to Receive/:abbr:`GRNI (Goods Received Not Invoiced)` or

Copy link
Contributor

@oomsveta oomsveta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, thanks a lot for your work!
I skimmed through the vanilla JavaScript code and noticed a few small things:

const idx = items.indexOf(null);
if (idx !== -1) {
console.log(items.slice(idx + 1).deref());
items = items.take(idx);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't items a const? You can't reassign it

@@ -0,0 +1,173 @@
/* global Immutable, React */
/* global createAtom, findAncestor */
/* global VALUATION_{STANDARDS,METHODS,JOURNALS,ENTRIES,REVIEWS} */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK brace expansion isn't supported

Comment on lines +58 to +60
const bold = document.createElement('b'),
defined = document.createTextNode(`${headText}:`);
bold.appendChild(defined);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updating the textContent directly would be lighter than creating a new text node

const bold = document.createElement('b');
bold.textContent = `${headText}:`;

label.appendChild(bold);
}

label.appendChild(document.createTextNode(tailText || headText));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same remark here

}

label.appendChild(document.createTextNode(tailText || headText));
label.normalize();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

normalize isn't in-place, I think this line is useless. Out of curiosity, why did you need to normalize it to begin with?

);
}));
function format(val, def) {
if (!val) { return def === undefined ? '' : def; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (!val) { return def === undefined ? '' : def; }
if (!val) { return def ?? ""; }

const items = this.props.items;
const idx = items.indexOf(null);
if (idx !== -1) {
// console.log(items.slice(idx + 1).deref());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forgotten console.log

An adaptation of the venerable business memento from 8.0 to the new
inventory valuation mechanics of Odoo 19.0 by scavenging and cobbling
together of the scripts `entries.js` and `coa-valuation.js`. The shared
data is kept in a separate file.

Additionally, we remove the old inventory valuation documentation.

Task ID: 5107300
@dade-odoo dade-odoo force-pushed the 19.0-inventory_valuation_cheatsheet-lugr branch from cfb5e89 to 7f1df8b Compare October 23, 2025 12:12
@dalaOdoo
Copy link
Contributor

@oomsveta Lulu is off until next week, can we move forward or are these change requests blocking points ? If yes can you adapt directly ?

@Felicious
Copy link
Contributor

@robodoo r+

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants