[IMP] stock: configurable product's weight UOM

This commit adds the possibility to chose between pounds and kilograms
to express the weight field on the product. This is done so that
companies that worked internally in pounds do not have to convert their
weights back to kilograms for a consistent computation of the rates in
delivery.

We complete the general settings with the selection of the weight's uom.
Validating the setting will create an ir.config.parameter. A static
method defined on product template will return the chosen UOM.

We display "weight_uom_name" on the form view so that the UOM is not
clickable/editable because we fear user would want to edit the UOM
instead of changing it in the res config.

We move the view definition allowing to fill the product's weight from
stock to product to help the generation of the intrastat report without
installing inventory.
This commit is contained in:
Pierre Masereel
2018-01-29 15:20:56 +01:00
committed by Simon Lejeune
parent 951cb8bf40
commit 52a85e57b9
8 changed files with 94 additions and 48 deletions
@@ -79,40 +79,42 @@
</div>
</div>
</div>
<field name="company_id" invisible="1"/>
<h2>Multi-company</h2>
<div class="row mt16 o_settings_container" name="multi_company">
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="group_multi_company"/>
</div>
<div class="o_setting_right_pane">
<label string="Multi-company" for="group_multi_company"/>
<div class="text-muted">
Manage multiple legal entities with separate accounting
<div id="multi_company">
<field name="company_id" invisible="1"/>
<h2>Multi-company</h2>
<div class="row mt16 o_settings_container" name="multi_company">
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="group_multi_company"/>
</div>
<div class="content-group" attrs="{'invisible': [('group_multi_company','=',False)]}">
<div class="mt16">
<button name="%(base.action_res_company_form)d" icon="fa-arrow-right" type="action" string="Companies" class="btn-link"/>
<div class="o_setting_right_pane">
<label string="Multi-company" for="group_multi_company"/>
<div class="text-muted">
Manage multiple legal entities with separate accounting
</div>
<div id="company_share_partner">
<field name="company_share_partner"/>
<label string="Common Contact Book" class="o_light_label" for="company_share_partner"/>
<div class="content-group" attrs="{'invisible': [('group_multi_company','=',False)]}">
<div class="mt16">
<button name="%(base.action_res_company_form)d" icon="fa-arrow-right" type="action" string="Companies" class="btn-link"/>
</div>
<div id="company_share_partner">
<field name="company_share_partner"/>
<label string="Common Contact Book" class="o_light_label" for="company_share_partner"/>
</div>
</div>
</div>
</div>
</div>
<div class="col-xs-12 col-md-6 o_setting_box" title="Configure company rules to automatically create SO/PO when one of your company sells/buys to another of your company." attrs="{'invisible': [('group_multi_company', '=', False)]}" id="inter_company">
<div class="o_setting_left_pane">
<field name="module_inter_company_rules" widget="upgrade_boolean"/>
</div>
<div class="o_setting_right_pane">
<label string="Inter-Company Transactions" for="module_inter_company_rules"/>
<div class="text-muted">
Automate inter-company transactions
<div class="col-xs-12 col-md-6 o_setting_box" title="Configure company rules to automatically create SO/PO when one of your company sells/buys to another of your company." attrs="{'invisible': [('group_multi_company', '=', False)]}" id="inter_company">
<div class="o_setting_left_pane">
<field name="module_inter_company_rules" widget="upgrade_boolean"/>
</div>
<div class="content-group" attrs="{'invisible': [('module_inter_company_rules','=',False)]}" id="inter_companies_rules">
<div class="mt16 text-warning"><strong>Save</strong> this page and come back here to set up the feature.</div>
<div class="o_setting_right_pane">
<label string="Inter-Company Transactions" for="module_inter_company_rules"/>
<div class="text-muted">
Automate inter-company transactions
</div>
<div class="content-group" attrs="{'invisible': [('module_inter_company_rules','=',False)]}" id="inter_companies_rules">
<div class="mt16 text-warning"><strong>Save</strong> this page and come back here to set up the feature.</div>
</div>
</div>
</div>
</div>
+6 -7
View File
@@ -51,12 +51,6 @@ class StockMoveLine(models.Model):
class StockPicking(models.Model):
_inherit = 'stock.picking'
def _default_uom(self):
weight_uom_id = self.env.ref('product.product_uom_kgm', raise_if_not_found=False)
if not weight_uom_id:
uom_categ_id = self.env.ref('product.product_uom_categ_kgm').id
weight_uom_id = self.env['product.uom'].search([('category_id', '=', uom_categ_id), ('factor', '=', 1)], limit=1)
return weight_uom_id
@api.one
@api.depends('move_line_ids')
@@ -89,7 +83,7 @@ class StockPicking(models.Model):
weight = fields.Float(compute='_cal_weight', digits=dp.get_precision('Stock Weight'), store=True)
carrier_tracking_ref = fields.Char(string='Tracking Reference', copy=False)
carrier_tracking_url = fields.Char(string='Tracking URL', compute='_compute_carrier_tracking_url')
weight_uom_id = fields.Many2one('product.uom', string='Unit of Measure', required=True, readonly="1", help="Unit of measurement for Weight", default=_default_uom)
weight_uom_id = fields.Many2one('product.uom', string='Unit of Measure', compute='_compute_weight_uom_id', help="Unit of measurement for Weight")
package_ids = fields.Many2many('stock.quant.package', compute='_compute_packages', string='Packages')
weight_bulk = fields.Float('Bulk Weight', compute='_compute_bulk_weight')
shipping_weight = fields.Float("Weight for Shipping", compute='_compute_shipping_weight')
@@ -99,6 +93,11 @@ class StockPicking(models.Model):
for picking in self:
picking.carrier_tracking_url = picking.carrier_id.get_tracking_link(picking) if picking.carrier_id and picking.carrier_tracking_ref else False
def _compute_weight_uom_id(self):
weight_uom_id = self.env['product.template']._get_weight_uom_id_from_ir_config_parameter()
for picking in self:
picking.weight_uom_id = weight_uom_id
@api.depends('move_lines')
def _cal_weight(self):
for picking in self:
+1 -1
View File
@@ -136,7 +136,7 @@ class ProductProduct(models.Model):
volume = fields.Float('Volume', help="The volume in m3.")
weight = fields.Float(
'Weight', digits=dp.get_precision('Stock Weight'),
help="The weight of the contents in Kg, not including any packaging, etc.")
help="Weight of the product, packaging not included. The unit of measure can be changed in the general settings")
pricelist_item_ids = fields.Many2many(
'product.pricelist.item', 'Pricelist Items', compute='_get_pricelist_items')
+21
View File
@@ -89,6 +89,8 @@ class ProductTemplate(models.Model):
'Weight', compute='_compute_weight', digits=dp.get_precision('Stock Weight'),
inverse='_set_weight', store=True,
help="The weight of the contents in Kg, not including any packaging, etc.")
weight_uom_id = fields.Many2one('product.uom', string='Weight Unit of Measure', compute='_compute_weight_uom_id')
weight_uom_name = fields.Char(string='Weight unit of measure label', related='weight_uom_id.name', readonly=True)
sale_ok = fields.Boolean(
'Can be Sold', default=True,
@@ -234,6 +236,25 @@ class ProductTemplate(models.Model):
for template in (self - unique_variants):
template.weight = 0.0
@api.model
def _get_weight_uom_id_from_ir_config_parameter(self):
""" Get the unit of measure to interpret the `weight` field. By default, we considerer
that weights are expressed in kilograms. Users can configure to express them in pounds
by adding an ir.config_parameter record with "product.product_weight_in_lbs" as key
and "1" as value.
"""
get_param = self.env['ir.config_parameter'].sudo().get_param
product_weight_in_lbs_param = get_param('product.weight_in_lbs')
if product_weight_in_lbs_param == '1':
return self.env.ref('product.product_uom_lb')
else:
return self.env.ref('product.product_uom_kgm')
def _compute_weight_uom_id(self):
weight_uom_id = self._get_weight_uom_id_from_ir_config_parameter()
for product_template in self:
product_template.weight_uom_id = weight_uom_id
@api.one
def _set_weight(self):
if len(self.product_variant_ids) == 1:
@@ -24,6 +24,10 @@ class ResConfigSettings(models.TransientModel):
implied_group='product.group_product_pricelist')
group_pricelist_item = fields.Boolean("Show pricelists to customers",
implied_group='product.group_pricelist_item')
product_weight_in_lbs = fields.Selection([
('0', 'Kilogram'),
('1', 'Pound'),
], 'Weight unit of measure', config_parameter='product.weight_in_lbs', default='0')
@api.model
+12
View File
@@ -55,6 +55,18 @@
<field name="currency_id" invisible="1"/>
<field name="product_variant_id" invisible="1"/>
</group>
<group name="group_lots_and_weight" attrs="{'invisible':[('type', 'not in', ['product', 'consu'])]}">
<label for="weight"/>
<div class="o_row" name="weight">
<field name="weight"/>
<span><field name="weight_uom_name"/></span>
</div>
<label for="volume"/>
<div class="o_row" name="volume">
<field name="volume" string="Volume"/>
<span>m³</span>
</div>
</group>
</group>
</page>
<page string="Sales" attrs="{'invisible':[('sale_ok','=',False)]}" name="sales">
@@ -9,6 +9,26 @@
<field name="company_share_product"/>
<label string="Common Product Catalog" class="o_light_label" for="company_share_product"/>
</xpath>
<xpath expr="//div[@id='multi_company']" position="before">
<h2>Products</h2>
<div class="row mt16 o_settings_container" id="product_general_settings">
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_left_pane">
</div>
<div class="o_setting_right_pane">
<label for="product_weight_in_lbs"/>
<div class="text-muted">
In which unit of measure do you manage your weights
</div>
<div class="content-group">
<div class="mt16">
<field name="product_weight_in_lbs" class="o_light_label" widget="radio"/>
</div>
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo>
-12
View File
@@ -97,18 +97,6 @@
</group>
</group>
<group name="inventory_valuation" position="after">
<group string="Logistics" name="group_lots_and_weight" attrs="{'invisible':[('type', 'not in', ['product', 'consu'])]}">
<label for="weight"/>
<div class="o_row" name="weight">
<field name="weight"/>
<span>kg</span>
</div>
<label for="volume"/>
<div class="o_row" name="volume">
<field name="volume" string="Volume"/>
<span>m³</span>
</div>
</group>
<group string="Counterpart Locations" name="stock_property" groups="base.group_no_one">
<field name="property_stock_production" domain="[('usage','=','production')]"/>
<field name="property_stock_inventory" domain="[('usage','=','inventory')]"/>