From c98562c9e09cecde9330d88a72b67b4dfac33b43 Mon Sep 17 00:00:00 2001 From: AlexPForgeFlow Date: Mon, 27 Jan 2025 12:37:31 +0100 Subject: [PATCH] [16.0][FIX] account_move_line_purchase_info: do not consider stock entry lines on revaluations Up to now, stock entries were considered in the revaluation process as they were stored on field invoice_lines. To avoid that we introduced a dedicated field to manage stock entries and avoid taking them into account in the revaluation odoo core process. --- account_move_line_purchase_info/README.rst | 7 +++++ .../__manifest__.py | 2 +- .../migrations/16.0.2.0.0/post-migration.py | 19 ++++++++++++ .../migrations/16.0.2.0.0/pre-migration.py | 31 +++++++++++++++++++ .../models/account_move.py | 26 +++++++++++++++- .../models/purchase_order.py | 19 +++--------- .../models/purchase_order_line.py | 6 +++- .../models/stock_move.py | 2 +- .../readme/DESCRIPTION.rst | 7 +++++ .../static/description/index.html | 18 ++++++++--- .../test_account_move_line_purchase_info.py | 2 +- 11 files changed, 114 insertions(+), 25 deletions(-) create mode 100644 account_move_line_purchase_info/migrations/16.0.2.0.0/post-migration.py create mode 100644 account_move_line_purchase_info/migrations/16.0.2.0.0/pre-migration.py diff --git a/account_move_line_purchase_info/README.rst b/account_move_line_purchase_info/README.rst index 93d745ea289..523ff1b0067 100644 --- a/account_move_line_purchase_info/README.rst +++ b/account_move_line_purchase_info/README.rst @@ -33,6 +33,13 @@ This module will add the purchase order line to journal items. The ultimate goal is to establish the purchase order line as one of the key fields to reconcile the Goods Received Not Invoiced accrual account. +Field purchase_line_id_oca it's necessary. In Odoo >=16 automatic +revaluation for a product with FIFO costing method only works if invoice +lines related to a purchase order line do not include stock journal items. +To aviod that purchase_line_id_oca includes invoice and stock journal items, +and we keep Odoo field invoice_lines just with bill lines. +- Check issue https://github.com/OCA/account-financial-tools/issues/2017 + **Table of contents** .. contents:: diff --git a/account_move_line_purchase_info/__manifest__.py b/account_move_line_purchase_info/__manifest__.py index 0b5dba7c84d..6354eb111a5 100644 --- a/account_move_line_purchase_info/__manifest__.py +++ b/account_move_line_purchase_info/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Account Move Line Purchase Info", "summary": "Introduces the purchase order line to the journal items", - "version": "16.0.1.0.0", + "version": "16.0.2.0.0", "author": "ForgeFlow, Odoo Community Association (OCA)", "website": "https://github.com/OCA/account-financial-tools", "category": "Generic", diff --git a/account_move_line_purchase_info/migrations/16.0.2.0.0/post-migration.py b/account_move_line_purchase_info/migrations/16.0.2.0.0/post-migration.py new file mode 100644 index 00000000000..3b10b23bfec --- /dev/null +++ b/account_move_line_purchase_info/migrations/16.0.2.0.0/post-migration.py @@ -0,0 +1,19 @@ +from openupgradelib import openupgrade + + +@openupgrade.migrate() +def migrate(env, version): + purchase_orders = env["purchase.order"].search([("state", "=", "purchase")]) + for order in purchase_orders: + valued_lines = order.order_line.invoice_lines.filtered( + lambda l: l.product_id + and l.product_id.cost_method != "standard" + and (not l.company_id.tax_lock_date or l.date > l.company_id.tax_lock_date) + ) + svls, _amls = valued_lines._apply_price_difference() + + if svls: + svls._validate_accounting_entries() + + bills = order.invoice_ids.filtered(lambda bill: bill.state == "posted") + bills._stock_account_anglo_saxon_reconcile_valuation() diff --git a/account_move_line_purchase_info/migrations/16.0.2.0.0/pre-migration.py b/account_move_line_purchase_info/migrations/16.0.2.0.0/pre-migration.py new file mode 100644 index 00000000000..d9412d87ede --- /dev/null +++ b/account_move_line_purchase_info/migrations/16.0.2.0.0/pre-migration.py @@ -0,0 +1,31 @@ +from openupgradelib import openupgrade + + +@openupgrade.migrate() +def migrate(env, version): + openupgrade.logged_query( + env.cr, + """ + ALTER TABLE account_move_line + ADD COLUMN IF NOT EXISTS purchase_line_id_oca INTEGER; + """, + ) + + openupgrade.logged_query( + env.cr, + """ + UPDATE account_move_line + SET purchase_line_id_oca = purchase_line_id; + """, + ) + + openupgrade.logged_query( + env.cr, + """ + UPDATE account_move_line + SET purchase_line_id = NULL + FROM account_move + WHERE account_move_line.move_id = account_move.id + AND account_move.move_type = 'entry'; + """, + ) diff --git a/account_move_line_purchase_info/models/account_move.py b/account_move_line_purchase_info/models/account_move.py index b8a6e1bbebd..f3c8016b79d 100644 --- a/account_move_line_purchase_info/models/account_move.py +++ b/account_move_line_purchase_info/models/account_move.py @@ -2,14 +2,38 @@ # (https://www.forgeflow.com) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). -from odoo import fields, models +from odoo import api, fields, models class AccountMoveLine(models.Model): _inherit = "account.move.line" + # Set related None, to make it compute and avoid base related to purchase_line_id purchase_order_id = fields.Many2one( comodel_name="purchase.order", + related=None, store=True, index=True, + compute="_compute_purchase_id", ) + + purchase_line_id_oca = fields.Many2one( + comodel_name="purchase.order.line", + string="Purchase line OCA", + store=True, + index=True, + compute="_compute_purchase_line_id_oca", + ) + + @api.depends("purchase_line_id") + def _compute_purchase_line_id_oca(self): + for rec in self: + if rec.purchase_line_id: + rec.purchase_line_id_oca = rec.purchase_line_id + + @api.depends("purchase_line_id", "purchase_line_id_oca") + def _compute_purchase_id(self): + for rec in self: + rec.purchase_order_id = ( + rec.purchase_line_id.order_id.id or rec.purchase_line_id_oca.order_id.id + ) diff --git a/account_move_line_purchase_info/models/purchase_order.py b/account_move_line_purchase_info/models/purchase_order.py index 11a05644e17..ce81c60a6b5 100644 --- a/account_move_line_purchase_info/models/purchase_order.py +++ b/account_move_line_purchase_info/models/purchase_order.py @@ -4,12 +4,12 @@ class PurchaseOrder(models.Model): _inherit = "purchase.order" - @api.depends("order_line.invoice_lines.move_id") + @api.depends("order_line.stock_invoice_lines.move_id") def _compute_journal_entries(self): for order in self: - journal_entries = order.mapped("order_line.invoice_lines.move_id").filtered( - lambda r: r.move_type == "entry" - ) + journal_entries = order.mapped( + "order_line.stock_invoice_lines.move_id" + ).filtered(lambda r: r.move_type == "entry") order.journal_entry_ids = journal_entries order.journal_entries_count = len(journal_entries) @@ -21,17 +21,6 @@ def _compute_journal_entries(self): string="Journal Entries", ) - @api.depends("order_line.invoice_lines.move_id") - def _compute_invoice(self): - """Overwritten compute to avoid show all Journal Entries with - purchase_order_line as invoice_lines One2many would take them into account.""" - for order in self: - invoices = order.order_line.invoice_lines.move_id.filtered( - lambda m: m.is_invoice(include_receipts=True) - ) - order.invoice_ids = invoices - order.invoice_count = len(invoices) - def action_view_journal_entries(self, invoices=False): """This function returns an action that display existing journal entries of given purchase order ids. When only one found, show the journal entry diff --git a/account_move_line_purchase_info/models/purchase_order_line.py b/account_move_line_purchase_info/models/purchase_order_line.py index 835259d2b3f..12ddd8618a3 100644 --- a/account_move_line_purchase_info/models/purchase_order_line.py +++ b/account_move_line_purchase_info/models/purchase_order_line.py @@ -1,12 +1,16 @@ # Copyright 2019-2020 ForgeFlow S.L. # (https://www.forgeflow.com) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). -from odoo import models +from odoo import fields, models class PurchaseOrderLine(models.Model): _inherit = "purchase.order.line" + stock_invoice_lines = fields.One2many( + "account.move.line", "purchase_line_id_oca", readonly=True, copy=False + ) + def name_get(self): result = [] orig_name = dict(super(PurchaseOrderLine, self).name_get()) diff --git a/account_move_line_purchase_info/models/stock_move.py b/account_move_line_purchase_info/models/stock_move.py index f5a4841594f..005894c1662 100644 --- a/account_move_line_purchase_info/models/stock_move.py +++ b/account_move_line_purchase_info/models/stock_move.py @@ -15,5 +15,5 @@ def _prepare_account_move_line( qty, cost, credit_account_id, debit_account_id, svl_id, description ) for line in res: - line[2]["purchase_line_id"] = self.purchase_line_id.id + line[2]["purchase_line_id_oca"] = self.purchase_line_id.id return res diff --git a/account_move_line_purchase_info/readme/DESCRIPTION.rst b/account_move_line_purchase_info/readme/DESCRIPTION.rst index feda547b9a1..7a05dd12021 100644 --- a/account_move_line_purchase_info/readme/DESCRIPTION.rst +++ b/account_move_line_purchase_info/readme/DESCRIPTION.rst @@ -2,3 +2,10 @@ This module will add the purchase order line to journal items. The ultimate goal is to establish the purchase order line as one of the key fields to reconcile the Goods Received Not Invoiced accrual account. + +Field purchase_line_id_oca it's necessary. In Odoo >=16 automatic +revaluation for a product with FIFO costing method only works if invoice +lines related to a purchase order line do not include stock journal items. +To aviod that purchase_line_id_oca includes invoice and stock journal items, +and we keep Odoo field invoice_lines just with bill lines. +- Check issue https://github.com/OCA/account-financial-tools/issues/2017 diff --git a/account_move_line_purchase_info/static/description/index.html b/account_move_line_purchase_info/static/description/index.html index 83ab814c3d8..8464dbe9348 100644 --- a/account_move_line_purchase_info/static/description/index.html +++ b/account_move_line_purchase_info/static/description/index.html @@ -1,4 +1,3 @@ - @@ -9,10 +8,11 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ +:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. +Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -275,7 +275,7 @@ margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: grey; } /* line numbers */ +pre.code .ln { color: gray; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -301,7 +301,7 @@ span.pre { white-space: pre } -span.problematic { +span.problematic, pre.problematic { color: red } span.section-subtitle { @@ -373,6 +373,12 @@

Account Move Line Purchase Info

This module will add the purchase order line to journal items.

The ultimate goal is to establish the purchase order line as one of the key fields to reconcile the Goods Received Not Invoiced accrual account.

+

Field purchase_line_id_oca it’s necessary. In Odoo >=16 automatic +revaluation for a product with FIFO costing method only works if invoice +lines related to a purchase order line do not include stock journal items. +To aviod that purchase_line_id_oca includes invoice and stock journal items, +and we keep Odoo field invoice_lines just with bill lines. +- Check issue https://github.com/OCA/account-financial-tools/issues/2017

Table of contents