[REF] account,hr_expense,sale: enforce uom domain
Enforce the domain of the UOM not by an onchange but by a domain. Example of an issue if the domain is enforced by an onchange: - create a order - add an order line - select the product - select an uom > the uom presented are the one from the product category. -Save - edit - select an uom > all UOM are presented even the ones of other categories This commit enforce this new logic at most places. task - 2003959 closes odoo/odoo#33741 Signed-off-by: Damien Bouvy (dbo) <dbo@odoo.com>
This commit is contained in:
committed by
Damien Bouvy
parent
b492bde6a1
commit
65613f5f83
@@ -179,7 +179,8 @@ class AccountAnalyticLine(models.Model):
|
||||
date = fields.Date('Date', required=True, index=True, default=fields.Date.context_today)
|
||||
amount = fields.Monetary('Amount', required=True, default=0.0)
|
||||
unit_amount = fields.Float('Quantity', default=0.0)
|
||||
product_uom_id = fields.Many2one('uom.uom', string='Unit of Measure')
|
||||
product_uom_id = fields.Many2one('uom.uom', string='Unit of Measure', domain="[('category_id', '=', product_uom_category_id)]")
|
||||
product_uom_category_id = fields.Many2one(related='product_uom_id.category_id', readonly=True)
|
||||
account_id = fields.Many2one('account.analytic.account', 'Analytic Account', required=True, ondelete='restrict', index=True)
|
||||
partner_id = fields.Many2one('res.partner', string='Partner')
|
||||
user_id = fields.Many2one('res.users', string='User', default=_default_user)
|
||||
|
||||
@@ -282,6 +282,7 @@
|
||||
<group name="amount" string="Amount">
|
||||
<field name="amount"/>
|
||||
<field name="unit_amount"/>
|
||||
<field name="product_uom_category_id" invisible="1"/>
|
||||
<field name="product_uom_id" class="oe_inline"/>
|
||||
<field name="currency_id" invisible="1"/>
|
||||
</group>
|
||||
|
||||
@@ -47,7 +47,8 @@ class HrExpense(models.Model):
|
||||
employee_id = fields.Many2one('hr.employee', string="Employee", required=True, readonly=True, states={'draft': [('readonly', False)], 'reported': [('readonly', False)], 'refused': [('readonly', False)]}, default=_default_employee_id, domain=lambda self: self._get_employee_id_domain())
|
||||
# product_id not required to allow create an expense without product via mail alias, but should be required on the view.
|
||||
product_id = fields.Many2one('product.product', string='Product', readonly=True, states={'draft': [('readonly', False)], 'reported': [('readonly', False)], 'refused': [('readonly', False)]}, domain=[('can_be_expensed', '=', True)])
|
||||
product_uom_id = fields.Many2one('uom.uom', string='Unit of Measure', readonly=True, states={'draft': [('readonly', False)], 'refused': [('readonly', False)]}, default=_default_product_uom_id)
|
||||
product_uom_id = fields.Many2one('uom.uom', string='Unit of Measure', readonly=True, states={'draft': [('readonly', False)], 'refused': [('readonly', False)]}, default=_default_product_uom_id, domain="[('category_id', '=', product_uom_category_id)]")
|
||||
product_uom_category_id = fields.Many2one(related='product_id.uom_id.category_id', readonly=True)
|
||||
unit_amount = fields.Float("Unit Price", readonly=True, required=True, states={'draft': [('readonly', False)], 'reported': [('readonly', False)], 'refused': [('readonly', False)]}, digits='Product Price')
|
||||
quantity = fields.Float(required=True, readonly=True, states={'draft': [('readonly', False)], 'reported': [('readonly', False)], 'refused': [('readonly', False)]}, digits='Product Unit of Measure', default=1)
|
||||
tax_ids = fields.Many2many('account.tax', 'expense_tax', 'expense_id', 'tax_id', string='Taxes')
|
||||
@@ -149,9 +150,6 @@ class HrExpense(models.Model):
|
||||
account = self.product_id.product_tmpl_id._get_product_accounts()['expense']
|
||||
if account:
|
||||
self.account_id = account
|
||||
return {'domain': {'product_uom_id': [('category_id', '=', self.product_id.uom_id.category_id.id)]}}
|
||||
else:
|
||||
return {'domain': {'product_uom_id': []}}
|
||||
|
||||
@api.onchange('product_uom_id')
|
||||
def _onchange_product_uom_id(self):
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
widget="many2one_barcode"
|
||||
/>
|
||||
<field name="unit_amount" required="1" widget="monetary" options="{'currency_field': 'currency_id'}"/>
|
||||
<field name="product_uom_category_id" invisible="1"/>
|
||||
<label for="quantity"/>
|
||||
<div class="o_row">
|
||||
<field name="quantity" class="oe_inline"/>
|
||||
|
||||
@@ -1105,7 +1105,8 @@ class SaleOrderLine(models.Model):
|
||||
product_template_id = fields.Many2one('product.template', string='Product Template', related="product_id.product_tmpl_id", domain=[('sale_ok', '=', True)])
|
||||
product_updatable = fields.Boolean(compute='_compute_product_updatable', string='Can Edit Product', readonly=True, default=True)
|
||||
product_uom_qty = fields.Float(string='Quantity', digits='Product Unit of Measure', required=True, default=1.0)
|
||||
product_uom = fields.Many2one('uom.uom', string='Unit of Measure')
|
||||
product_uom = fields.Many2one('uom.uom', string='Unit of Measure', domain="[('category_id', '=', product_uom_category_id)]")
|
||||
product_uom_category_id = fields.Many2one(related='product_id.uom_id.category_id', readonly=True)
|
||||
product_custom_attribute_value_ids = fields.One2many('product.attribute.custom.value', 'sale_order_line_id', string='User entered custom product attribute values')
|
||||
|
||||
# M2M holding the values of product.attribute with create_variant field set to 'no_variant'
|
||||
@@ -1360,7 +1361,7 @@ class SaleOrderLine(models.Model):
|
||||
@api.onchange('product_id')
|
||||
def product_id_change(self):
|
||||
if not self.product_id:
|
||||
return {'domain': {'product_uom': []}}
|
||||
return
|
||||
|
||||
# remove the is_custom values that don't belong to this template
|
||||
for pacv in self.product_custom_attribute_value_ids:
|
||||
@@ -1373,7 +1374,6 @@ class SaleOrderLine(models.Model):
|
||||
self.product_no_variant_attribute_value_ids -= ptav
|
||||
|
||||
vals = {}
|
||||
domain = {'product_uom': [('category_id', '=', self.product_id.uom_id.category_id.id)]}
|
||||
if not self.product_uom or (self.product_id.uom_id.id != self.product_uom.id):
|
||||
vals['product_uom'] = self.product_id.uom_id
|
||||
vals['product_uom_qty'] = self.product_uom_qty or 1.0
|
||||
@@ -1387,8 +1387,6 @@ class SaleOrderLine(models.Model):
|
||||
uom=self.product_uom.id
|
||||
)
|
||||
|
||||
result = {'domain': domain}
|
||||
|
||||
vals.update(name=self.get_sale_order_line_multiline_description_sale(product))
|
||||
|
||||
self._compute_tax_id()
|
||||
@@ -1399,6 +1397,7 @@ class SaleOrderLine(models.Model):
|
||||
|
||||
title = False
|
||||
message = False
|
||||
result = {}
|
||||
warning = {}
|
||||
if product.sale_line_warn != 'no-message':
|
||||
title = _("Warning for %s") % product.name
|
||||
|
||||
@@ -309,6 +309,7 @@
|
||||
TODO: at some point we want to fix this in the framework so that an invisible field is not required.
|
||||
-->
|
||||
<field name="sequence" invisible="1"/>
|
||||
<field name="product_uom_category_id" invisible="1"/>
|
||||
<group>
|
||||
<group attrs="{'invisible': [('display_type', '!=', False)]}">
|
||||
<field name="product_updatable" invisible="1"/>
|
||||
@@ -400,6 +401,7 @@
|
||||
<field name="sequence" widget="handle" />
|
||||
<!-- We do not display the type because we don't want the user to be bothered with that information if he has no section or note. -->
|
||||
<field name="display_type" invisible="1"/>
|
||||
<field name="product_uom_category_id" invisible="1"/>
|
||||
|
||||
<field name="product_updatable" invisible="1"/>
|
||||
<field
|
||||
|
||||
@@ -169,7 +169,8 @@ class SaleOrderOption(models.Model):
|
||||
product_id = fields.Many2one('product.product', 'Product', required=True, domain=[('sale_ok', '=', True)])
|
||||
price_unit = fields.Float('Unit Price', required=True, digits='Product Price')
|
||||
discount = fields.Float('Discount (%)', digits='Discount')
|
||||
uom_id = fields.Many2one('uom.uom', 'Unit of Measure ', required=True)
|
||||
uom_id = fields.Many2one('uom.uom', 'Unit of Measure ', required=True, domain="[('category_id', '=', product_uom_category_id)]")
|
||||
product_uom_category_id = fields.Many2one(related='product_id.uom_id.category_id', readonly=True)
|
||||
quantity = fields.Float('Quantity', required=True, digits='Product UoS', default=1)
|
||||
sequence = fields.Integer('Sequence', help="Gives the sequence order when displaying a list of optional products.")
|
||||
|
||||
|
||||
@@ -68,7 +68,8 @@ class SaleOrderTemplateLine(models.Model):
|
||||
price_unit = fields.Float('Unit Price', required=True, digits='Product Price')
|
||||
discount = fields.Float('Discount (%)', digits='Discount', default=0.0)
|
||||
product_uom_qty = fields.Float('Quantity', required=True, digits='Product UoS', default=1)
|
||||
product_uom_id = fields.Many2one('uom.uom', 'Unit of Measure')
|
||||
product_uom_id = fields.Many2one('uom.uom', 'Unit of Measure', domain="[('category_id', '=', product_uom_category_id)]")
|
||||
product_uom_category_id = fields.Many2one(related='product_id.uom_id.category_id', readonly=True)
|
||||
|
||||
display_type = fields.Selection([
|
||||
('line_section', "Section"),
|
||||
@@ -84,8 +85,6 @@ class SaleOrderTemplateLine(models.Model):
|
||||
self.name = name
|
||||
self.price_unit = self.product_id.lst_price
|
||||
self.product_uom_id = self.product_id.uom_id.id
|
||||
domain = {'product_uom_id': [('category_id', '=', self.product_id.uom_id.category_id.id)]}
|
||||
return {'domain': domain}
|
||||
|
||||
@api.onchange('product_uom_id')
|
||||
def _onchange_product_uom(self):
|
||||
@@ -124,7 +123,8 @@ class SaleOrderTemplateOption(models.Model):
|
||||
product_id = fields.Many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], required=True)
|
||||
price_unit = fields.Float('Unit Price', required=True, digits='Product Price')
|
||||
discount = fields.Float('Discount (%)', digits='Discount')
|
||||
uom_id = fields.Many2one('uom.uom', 'Unit of Measure ', required=True)
|
||||
uom_id = fields.Many2one('uom.uom', 'Unit of Measure ', required=True, domain="[('category_id', '=', product_uom_category_id)]")
|
||||
product_uom_category_id = fields.Many2one(related='product_id.uom_id.category_id', readonly=True)
|
||||
quantity = fields.Float('Quantity', required=True, digits='Product UoS', default=1)
|
||||
|
||||
@api.onchange('product_id')
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
-->
|
||||
<field name="sequence" invisible="1"/>
|
||||
<field name="display_type" invisible="1"/>
|
||||
<field name="product_uom_category_id" invisible="1"/>
|
||||
<group attrs="{'invisible': [('display_type', '!=', False)]}">
|
||||
<group>
|
||||
<field name="product_id" attrs="{'required': [('display_type', '=', False)]}"/>
|
||||
@@ -85,6 +86,7 @@
|
||||
<field name="product_id"/>
|
||||
<field name="name" widget="section_and_note_text"/>
|
||||
<field name="product_uom_qty"/>
|
||||
<field name="product_uom_category_id" invisible="1"/>
|
||||
<field
|
||||
name="product_uom_id"
|
||||
groups="uom.group_uom"
|
||||
@@ -101,6 +103,7 @@
|
||||
<field name="product_id"/>
|
||||
<field name="name"/>
|
||||
<field name="quantity"/>
|
||||
<field name="product_uom_category_id" invisible="1"/>
|
||||
<field name="uom_id" groups="uom.group_uom"/>
|
||||
<field name="price_unit" invisible="1"/>
|
||||
<field name="discount" groups="sale.group_discount_per_so_line"/>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<field name="product_id" domain="[('sale_ok', '=', True), '|', ('company_id', '=', False), ('company_id', '=', parent.company_id)]"/>
|
||||
<field name="name"/>
|
||||
<field name="quantity"/>
|
||||
<field name="product_uom_category_id" invisible="1"/>
|
||||
<field name="uom_id" groups="uom.group_uom"/>
|
||||
<field name="price_unit"/>
|
||||
<field name="discount" groups="sale.group_discount_per_so_line"/>
|
||||
@@ -71,6 +72,7 @@
|
||||
<field name="name" optional="show"/>
|
||||
<field name="quantity"/>
|
||||
<field name="uom_id" string="UoM" groups="uom.group_uom" optional="show"/>
|
||||
<field name="product_uom_category_id" invisible="1"/>
|
||||
<field name="price_unit"/>
|
||||
<field name="discount" string="Disc.%" groups="sale.group_discount_per_so_line" optional="show"/>
|
||||
<field name="is_present" invisible="1" />
|
||||
|
||||
Reference in New Issue
Block a user