diff --git a/addons/l10n_ar/views/uom_uom_view.xml b/addons/l10n_ar/views/uom_uom_view.xml
index 5a02b9318ca..218247e0712 100644
--- a/addons/l10n_ar/views/uom_uom_view.xml
+++ b/addons/l10n_ar/views/uom_uom_view.xml
@@ -23,4 +23,15 @@
+
+ uom.category.form
+ uom.category
+
+
+
+
+
+
+
+
diff --git a/addons/l10n_in/views/uom_uom_views.xml b/addons/l10n_in/views/uom_uom_views.xml
index 237ce736788..0e012a4b374 100644
--- a/addons/l10n_in/views/uom_uom_views.xml
+++ b/addons/l10n_in/views/uom_uom_views.xml
@@ -10,4 +10,15 @@
+
+
+ uom.category.form
+ uom.category
+
+
+
+
+
+
+
diff --git a/addons/purchase/views/purchase_views.xml b/addons/purchase/views/purchase_views.xml
index 35683066287..54757c71a01 100644
--- a/addons/purchase/views/purchase_views.xml
+++ b/addons/purchase/views/purchase_views.xml
@@ -44,7 +44,7 @@
+ parent="purchase.menu_unit_of_measure_in_config_purchase" sequence="5" groups="base.group_no_one"/>
-
-
-
+
+
+
diff --git a/addons/stock/views/stock_menu_views.xml b/addons/stock/views/stock_menu_views.xml
index 6da09922ab3..3bfcad370eb 100644
--- a/addons/stock/views/stock_menu_views.xml
+++ b/addons/stock/views/stock_menu_views.xml
@@ -36,7 +36,7 @@
+ parent="product_uom_menu" sequence="35" groups="base.group_no_one"/>
diff --git a/addons/uom/models/uom_uom.py b/addons/uom/models/uom_uom.py
index 2fa8267f498..7ffd1cfea7a 100644
--- a/addons/uom/models/uom_uom.py
+++ b/addons/uom/models/uom_uom.py
@@ -13,11 +13,42 @@ class UoMCategory(models.Model):
name = fields.Char('Unit of Measure Category', required=True, translate=True)
+ uom_ids = fields.One2many('uom.uom', 'category_id')
+ reference_uom_id = fields.Many2one('uom.uom', "Reference UoM", store=False, help="Dummy field to keep track of reference uom change")
+
+ @api.onchange('uom_ids')
+ def _onchange_uom_ids(self):
+ if len(self.uom_ids) == 1:
+ self.uom_ids[0].uom_type = 'reference'
+ self.uom_ids[0].factor = 1
+ else:
+ reference_count = sum(uom.uom_type == 'reference' for uom in self.uom_ids)
+ if reference_count == 0 and self._origin.id:
+ return {
+ 'warning': {
+ 'title': _('Warning!'),
+ 'message': _("UoM category %s should have a reference unit of measure.") % self.name
+ }
+ }
+ if self.reference_uom_id:
+ new_reference = self.uom_ids.filtered(lambda o: o.uom_type == 'reference' and o._origin.id != self.reference_uom_id.id)
+ else:
+ new_reference = self.uom_ids.filtered(lambda o: o.uom_type == 'reference' and o._origin.uom_type != 'reference')
+ if new_reference:
+ other_uoms = self.uom_ids - new_reference
+ for uom in other_uoms:
+ uom.factor = uom._origin.factor / (new_reference._origin.factor or 1)
+ if uom.factor > 1:
+ uom.uom_type = 'smaller'
+ else:
+ uom.uom_type = 'bigger'
+ self.reference_uom_id = new_reference._origin.id
+
class UoM(models.Model):
_name = 'uom.uom'
_description = 'Product Unit of Measure'
- _order = "name"
+ _order = "factor DESC, id"
def _unprotected_uom_xml_ids(self):
return [
@@ -46,6 +77,8 @@ class UoM(models.Model):
('reference', 'Reference Unit of Measure for this category'),
('smaller', 'Smaller than the reference Unit of Measure')], 'Type',
default='reference', required=True)
+ ratio = fields.Float('Combined Ratio', compute='_compute_ratio', inverse='_set_ratio', store=False)
+ color = fields.Integer('Color', compute='_compute_color')
_sql_constraints = [
('factor_gt_zero', 'CHECK (factor!=0)', 'The conversion ratio for a unit of measure cannot be 0!'),
@@ -53,11 +86,48 @@ class UoM(models.Model):
('factor_reference_is_one', "CHECK((uom_type = 'reference' AND factor = 1.0) OR (uom_type != 'reference'))", "The reference unit must have a conversion factor equal to 1.")
]
+ def _check_category_reference_uniqueness(self):
+ for category in self.category_id:
+ if not category.uom_ids:
+ continue
+ reference_count = sum(
+ uom.uom_type == 'reference' for uom in category.uom_ids)
+ if reference_count > 1:
+ raise ValidationError(_("UoM category %s should only have one reference unit of measure.") % category.name)
+ elif reference_count == 0:
+ raise ValidationError(_("UoM category %s should have a reference unit of measure.") % category.name)
+
@api.depends('factor')
def _compute_factor_inv(self):
for uom in self:
uom.factor_inv = uom.factor and (1.0 / uom.factor) or 0.0
+ @api.depends('uom_type', 'factor')
+ def _compute_ratio(self):
+ for uom in self:
+ if uom.uom_type == 'reference':
+ uom.ratio = 1
+ elif uom.uom_type == 'bigger':
+ uom.ratio = uom.factor_inv
+ else:
+ uom.ratio = uom.factor
+
+ def _set_ratio(self):
+ if self.uom_type == 'reference':
+ self.factor = 1
+ elif self.uom_type == 'bigger':
+ self.factor = 1 / self.ratio
+ else:
+ self.factor = self.ratio
+
+ @api.depends('uom_type')
+ def _compute_color(self):
+ for uom in self:
+ if uom.uom_type == 'reference':
+ uom.color = 7
+ else:
+ uom.color = 0
+
@api.onchange('uom_type')
def _onchange_uom_type(self):
if self.uom_type == 'reference':
@@ -80,49 +150,26 @@ class UoM(models.Model):
}
}
- @api.constrains('category_id', 'uom_type', 'active')
- def _check_category_reference_uniqueness(self):
- """ Force the existence of only one UoM reference per category
- NOTE: this is a constraint on the all table. This might not be a good practice, but this is
- not possible to do it in SQL directly.
- """
- category_ids = self.mapped('category_id').ids
- self.env['uom.uom'].flush(['category_id', 'uom_type', 'active'])
- self._cr.execute("""
- SELECT C.id AS category_id, count(U.id) AS uom_count
- FROM uom_category C
- LEFT JOIN uom_uom U ON C.id = U.category_id AND uom_type = 'reference' AND U.active = 't'
- WHERE C.id IN %s
- GROUP BY C.id
- """, (tuple(category_ids),))
- for uom_data in self._cr.dictfetchall():
- if uom_data['uom_count'] == 0:
- raise ValidationError(_("UoM category %s should have a reference unit of measure. If you just created a new category, please record the 'reference' unit first.") % (self.env['uom.category'].browse(uom_data['category_id']).name,))
- if uom_data['uom_count'] > 1:
- raise ValidationError(_("UoM category %s should only have one reference unit of measure.") % (self.env['uom.category'].browse(uom_data['category_id']).name,))
-
- @api.constrains('category_id')
- def _validate_uom_category(self):
- for uom in self:
- reference_uoms = self.env['uom.uom'].search([
- ('category_id', '=', uom.category_id.id),
- ('uom_type', '=', 'reference')])
- if len(reference_uoms) > 1:
- raise ValidationError(_("UoM category %s should only have one reference unit of measure.") % (self.category_id.name))
-
@api.model_create_multi
def create(self, vals_list):
for values in vals_list:
if 'factor_inv' in values:
factor_inv = values.pop('factor_inv')
values['factor'] = factor_inv and (1.0 / factor_inv) or 0.0
- return super(UoM, self).create(vals_list)
+ res = super(UoM, self).create(vals_list)
+ res._check_category_reference_uniqueness()
+ return res
def write(self, values):
if 'factor_inv' in values:
factor_inv = values.pop('factor_inv')
values['factor'] = factor_inv and (1.0 / factor_inv) or 0.0
- return super(UoM, self).write(values)
+
+ res = super(UoM, self).write(values)
+ if ('uom_type' not in values or values['uom_type'] != 'reference') and\
+ not self.env.context.get('allow_to_change_reference'):
+ self._check_category_reference_uniqueness()
+ return res
@api.ondelete(at_uninstall=False)
def _unlink_except_master_data(self):
diff --git a/addons/uom/views/uom_uom_views.xml b/addons/uom/views/uom_uom_views.xml
index 91a883c85b0..c8e39b68849 100644
--- a/addons/uom/views/uom_uom_views.xml
+++ b/addons/uom/views/uom_uom_views.xml
@@ -22,7 +22,7 @@
-
+