# -*- 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 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