141 lines
5.3 KiB
Python
141 lines
5.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
from odoo import models, fields, api
|
|
from lxml import etree
|
|
|
|
class PurchaseOrder(models.Model):
|
|
_inherit = 'purchase.order'
|
|
|
|
hide_confirm_order_send_rfq = fields.Boolean(
|
|
compute='_compute_hide_fields',
|
|
store=False,
|
|
help="Technical field computed from user settings to determine button visibility"
|
|
)
|
|
hide_purchase_prices = fields.Boolean(
|
|
compute='_compute_hide_fields',
|
|
store=False,
|
|
help="Technical field computed from user settings to determine price visibility"
|
|
)
|
|
|
|
def _compute_hide_fields(self):
|
|
# Retrieve the configuration settings dynamically from the current user
|
|
current_user = self.env.user
|
|
hide_buttons = current_user.hide_confirm_order_send_rfq
|
|
hide_prices = current_user.hide_purchase_prices
|
|
for order in self:
|
|
order.hide_confirm_order_send_rfq = hide_buttons
|
|
order.hide_purchase_prices = hide_prices
|
|
|
|
@api.model
|
|
def get_views(self, views, options=None):
|
|
res = super().get_views(views, options)
|
|
|
|
# Check current user configuration settings
|
|
current_user = self.env.user
|
|
hide_buttons = current_user.hide_confirm_order_send_rfq
|
|
hide_prices = current_user.hide_purchase_prices
|
|
|
|
if not (hide_buttons or hide_prices):
|
|
return res
|
|
|
|
for view_type, view_data in res.get('views', {}).items():
|
|
arch_str = view_data.get('arch')
|
|
if not arch_str:
|
|
continue
|
|
|
|
try:
|
|
doc = etree.fromstring(arch_str.encode('utf-8'))
|
|
except Exception:
|
|
continue
|
|
|
|
modified = False
|
|
|
|
# 1. Dynamically hide Confirm Order and Send RFQ buttons
|
|
if hide_buttons:
|
|
for btn in doc.xpath("//button[@name='action_rfq_send' or @name='button_confirm']"):
|
|
btn.set('invisible', '1')
|
|
modified = True
|
|
|
|
# 2. Dynamically hide all price, subtotal, taxes, and total elements
|
|
if hide_prices:
|
|
price_fields = {
|
|
'price_unit', 'taxes_id', 'price_subtotal', 'price_total', 'price_tax',
|
|
'amount_untaxed', 'amount_tax', 'amount_total', 'amount_total_cc',
|
|
'tax_totals', 'discount'
|
|
}
|
|
|
|
# Check all <field> tags
|
|
for field in doc.xpath("//field"):
|
|
fname = field.get('name')
|
|
if fname in price_fields:
|
|
# Determine if this field is inside a list or tree view (columns)
|
|
is_column = False
|
|
p = field.getparent()
|
|
while p is not None:
|
|
if p.tag in ('tree', 'list'):
|
|
is_column = True
|
|
break
|
|
p = p.getparent()
|
|
|
|
if is_column:
|
|
field.set('column_invisible', 'True')
|
|
else:
|
|
field.set('invisible', '1')
|
|
modified = True
|
|
|
|
# Hide any subtotal footer layouts
|
|
for el in doc.xpath("//group[contains(@class, 'oe_subtotal_footer')] | //div[contains(@class, 'oe_subtotal_footer')]"):
|
|
el.set('invisible', '1')
|
|
modified = True
|
|
|
|
if modified:
|
|
view_data['arch'] = etree.tostring(doc, encoding='utf-8').decode('utf-8')
|
|
|
|
return res
|
|
|
|
class PurchaseOrderLine(models.Model):
|
|
_inherit = 'purchase.order.line'
|
|
|
|
@api.model
|
|
def get_views(self, views, options=None):
|
|
res = super().get_views(views, options)
|
|
if not self.env.user.hide_purchase_prices:
|
|
return res
|
|
|
|
for view_type, view_data in res.get('views', {}).items():
|
|
arch_str = view_data.get('arch')
|
|
if not arch_str:
|
|
continue
|
|
|
|
try:
|
|
doc = etree.fromstring(arch_str.encode('utf-8'))
|
|
except Exception:
|
|
continue
|
|
|
|
modified = False
|
|
price_fields = {
|
|
'price_unit', 'price_unit_product_uom', 'price_subtotal',
|
|
'price_total', 'price_tax', 'discount', 'taxes_id'
|
|
}
|
|
|
|
for field in doc.xpath("//field"):
|
|
if field.get('name') in price_fields:
|
|
is_column = False
|
|
p = field.getparent()
|
|
while p is not None:
|
|
if p.tag in ('tree', 'list'):
|
|
is_column = True
|
|
break
|
|
p = p.getparent()
|
|
|
|
if is_column:
|
|
field.set('column_invisible', 'True')
|
|
else:
|
|
field.set('invisible', '1')
|
|
modified = True
|
|
|
|
if modified:
|
|
view_data['arch'] = etree.tostring(doc, encoding='utf-8').decode('utf-8')
|
|
|
|
return res
|
|
|