-
Couldn't load subscription status.
- Fork 10.4k
[ADD] Inventory: add stock valuation cheat sheet #14906
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
8a12b20 to
3966c78
Compare
|
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:
Approving this now to support the launch timeline. Our team would, however, like to revisit this soon to make revisions aimed at improving readability! (: |
|
@Felicious we can discuss these on discord. cc @lugr-odoo |
a5bd224 to
65712f8
Compare
65712f8 to
85fb613
Compare
|
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. |
e5f7d30 to
ce6e1d6
Compare
|
@Felicious @dade-odoo we know this is a big PR but we need it asap |
There was a problem hiding this 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>` | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra line
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 (:
| 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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. |
| .. 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)`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| .. 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)`. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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. |
| 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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. |
91ac8b5 to
cfb5e89
Compare
|
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. |
|
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! |
There was a problem hiding this 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
|
|
||
| .. important:: | ||
| This documentation is for Odoo 19 or later. | ||
| :ref:`Discover why we changed. <changes-in-19>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| .. important:: | |
| This documentation is for Odoo 19 or later. | |
| :ref:`Discover why we changed. <changes-in-19>` |
|
|
||
| .. _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` | | ||
| +-----------------------+--------------------------------+--------------------------------+ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| .. _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` | | |
| +-----------------------+--------------------------------+--------------------------------+ |
There was a problem hiding this comment.
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.
|
|
||
| .. image:: cheat_sheet/total-value.png | ||
| :scale: 90% |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| .. 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:Valueand, optionally, a :guilabel:Description.
| In Accounting | ||
| ------------- | ||
|
|
||
| Open :menuselection:`Review --> Inventory Valuation` to have a look at the difference between the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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. |
| Open | ||
| :menuselection:`Review --> Invoices not received, Invoices to be issued, Prepaid expenses and Deferred Revenues` | ||
| to easily record these entries. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| (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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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 |
There was a problem hiding this 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); |
There was a problem hiding this comment.
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} */ | |||
There was a problem hiding this comment.
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
| const bold = document.createElement('b'), | ||
| defined = document.createTextNode(`${headText}:`); | ||
| bold.appendChild(defined); |
There was a problem hiding this comment.
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)); |
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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()); |
There was a problem hiding this comment.
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
cfb5e89 to
7f1df8b
Compare
|
@oomsveta Lulu is off until next week, can we move forward or are these change requests blocking points ? If yes can you adapt directly ? |
|
@robodoo r+ |

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