Add update price button with notification to product views

- Add action_update_list_price button in form and list views
- Button shows only when compute type is not manual_update
- Return notification message with update results
- Invalidate cache to refresh UI automatically
- Show updated products with old and new prices
- Display skipped products with manual update mode
This commit is contained in:
snt 2026-02-11 21:04:18 +01:00
parent 4d23e98f7b
commit 2a480b74bb
2 changed files with 77 additions and 9 deletions

View file

@ -3,10 +3,12 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import exceptions, models, fields, api, _
from odoo.exceptions import UserError
import logging
import math
from odoo import _
from odoo import fields
from odoo import models
from odoo.exceptions import UserError
_logger = logging.getLogger(__name__)
@ -131,6 +133,9 @@ class ProductTemplate(models.Model):
)
def action_update_list_price(self):
updated_products = []
skipped_products = []
for template in self:
if template.last_purchase_price_compute_type != "manual_update":
# First compute the theoretical price
@ -146,6 +151,53 @@ class ProductTemplate(models.Model):
old_price,
template.list_price,
)
updated_products.append(
(
template.name or template.default_code,
old_price,
template.list_price,
)
)
else:
skipped_products.append(template.name or template.default_code)
# Invalidate cache to refresh UI
self.invalidate_recordset(
["list_price", "list_price_theoritical", "last_purchase_price_updated"]
)
# Build notification message
message = ""
if updated_products:
message += _("✓ Products updated: %s") % len(updated_products)
if len(updated_products) <= 5:
message += "\n\n"
for name, old, new in updated_products:
message += _("%s: %.2f%.2f\n") % (name, old, new)
if skipped_products:
if message:
message += "\n\n"
message += _("⚠ Skipped (manual update): %s") % len(skipped_products)
if len(skipped_products) <= 5:
message += "\n"
for name in skipped_products:
message += _("%s\n") % name
if not updated_products and not skipped_products:
message = _("No products to update.")
return {
"type": "ir.actions.client",
"tag": "display_notification",
"params": {
"title": _("Price Update"),
"message": message,
"type": "success" if updated_products else "warning",
"sticky": False,
"next": {"type": "ir.actions.act_window_close"},
},
}
def price_compute(
self, price_type, uom=None, currency=None, company=False, date=False

View file

@ -16,6 +16,14 @@
<xpath expr="//group[@name='group_standard_price']" position="after">
<group string="Automatic Price Update">
<field name="last_purchase_price_compute_type" />
<button
name="action_update_list_price"
type="object"
string="Update Price"
class="oe_highlight"
icon="fa-refresh"
invisible="last_purchase_price_compute_type == 'manual_update'"
/>
<field
name="last_purchase_price_received"
widget="monetary"
@ -42,6 +50,14 @@
<xpath expr="//field[@name='list_price']" position="after">
<field name="list_price_theoritical" optional="hide" />
<field name="last_purchase_price_received" optional="hide" />
<field name="last_purchase_price_compute_type" column_invisible="1" />
<button
name="action_update_list_price"
type="object"
string="Update Price"
icon="fa-refresh"
invisible="last_purchase_price_compute_type == 'manual_update'"
/>
</xpath>
</field>
</record>