diff --git a/lighting/i18n/es.po b/lighting/i18n/es.po index 19704c4a..a0ae7a9e 100644 --- a/lighting/i18n/es.po +++ b/lighting/i18n/es.po @@ -2568,6 +2568,11 @@ msgstr "Es max. potencia" msgid "Is recommended accessory" msgstr "" +#. module: lighting +#: model:ir.model.fields,field_description:lighting.field_lighting_product__is_spare_part +msgid "Is spare part" +msgstr "Es recambio" + #. module: lighting #: model:ir.model.constraint,message:lighting.constraint_lighting_product_voltage_voltage_uniq msgid "It already exists another voltage with the same parameters" @@ -3442,6 +3447,11 @@ msgstr "" msgid "P. rec. acc." msgstr "" +#. module: lighting +#: model_terms:ir.ui.view,arch_db:lighting.product_form_view +msgid "P. sp. parts" +msgstr "P. recambios" + #. module: lighting #: model:ir.model.fields,field_description:lighting.field_lighting_product_category__parent_id #: model:ir.model.fields,field_description:lighting.field_lighting_product_group__parent_id @@ -4637,6 +4647,13 @@ msgstr "Fuentes" msgid "Spanish" msgstr "" +#. module: lighting +#: model:ir.model.fields,field_description:lighting.field_lighting_product__spare_part_ids +#: model_terms:ir.ui.view,arch_db:lighting.product_form_view +#: model_terms:ir.ui.view,arch_db:lighting.lighting_product_view +msgid "Spare parts" +msgstr "Recambios" + #. module: lighting #: model:ir.model,name:lighting.model_lighting_product_special_spectrum msgid "Special Spectrum" diff --git a/lighting/i18n/fr.po b/lighting/i18n/fr.po index 06e8c008..01903a28 100644 --- a/lighting/i18n/fr.po +++ b/lighting/i18n/fr.po @@ -2561,6 +2561,11 @@ msgstr "Est max. En watts" msgid "Is recommended accessory" msgstr "" +#. module: lighting +#: model:ir.model.fields,field_description:lighting.field_lighting_product__is_spare_part +msgid "Is spare part" +msgstr "Est pièce de rechange" + #. module: lighting #: model:ir.model.constraint,message:lighting.constraint_lighting_product_voltage_voltage_uniq msgid "It already exists another voltage with the same parameters" @@ -3440,6 +3445,11 @@ msgstr "" msgid "P. rec. acc." msgstr "" +#. module: lighting +#: model_terms:ir.ui.view,arch_db:lighting.product_form_view +msgid "P. sp. parts" +msgstr "P. pièces" + #. module: lighting #: model:ir.model.fields,field_description:lighting.field_lighting_product_category__parent_id #: model:ir.model.fields,field_description:lighting.field_lighting_product_group__parent_id @@ -4635,6 +4645,13 @@ msgstr "Sources" msgid "Spanish" msgstr "" +#. module: lighting +#: model:ir.model.fields,field_description:lighting.field_lighting_product__spare_part_ids +#: model_terms:ir.ui.view,arch_db:lighting.product_form_view +#: model_terms:ir.ui.view,arch_db:lighting.lighting_product_view +msgid "Spare parts" +msgstr "Pièces de rechange" + #. module: lighting #: model:ir.model,name:lighting.model_lighting_product_special_spectrum msgid "Special Spectrum" diff --git a/lighting/i18n/pt.po b/lighting/i18n/pt.po index 93b832e0..d86f734d 100644 --- a/lighting/i18n/pt.po +++ b/lighting/i18n/pt.po @@ -2444,6 +2444,23 @@ msgstr "Controle remoto" msgid "Recommended accessories" msgstr "Acessórios recomendados" +#. module: lighting +#: model:ir.model.fields,field_description:lighting.field_lighting_product__spare_part_ids +#: model_terms:ir.ui.view,arch_db:lighting.product_form_view +#: model_terms:ir.ui.view,arch_db:lighting.lighting_product_view +msgid "Spare parts" +msgstr "Peças sobressalentes" + +#. module: lighting +#: model:ir.model.fields,field_description:lighting.field_lighting_product__is_spare_part +msgid "Is spare part" +msgstr "É peça sobressalente" + +#. module: lighting +#: model_terms:ir.ui.view,arch_db:lighting.product_form_view +msgid "P. sp. parts" +msgstr "P. peças" + #. module: lighting #: model:ir.model.fields,field_description:lighting.field_lighting_product_required_ids #: model:ir.ui.view,arch_db:lighting.product_form_view diff --git a/lighting/models/product.py b/lighting/models/product.py index 3741ea3d..ba271ae6 100644 --- a/lighting/models/product.py +++ b/lighting/models/product.py @@ -1357,6 +1357,66 @@ def _search_is_required_accessory(self, operator, value): tracking=True, ) + # Spare parts tab + spare_part_ids = fields.Many2many( + comodel_name="lighting.product", + relation="lighting_product_spare_part_rel", + column1="product_id", + column2="spare_part_id", + string="Spare parts", + tracking=True, + ) + parent_spare_part_product_count = fields.Integer( + compute="_compute_parent_spare_part_product_count" + ) + + @api.depends("spare_part_ids") + def _compute_parent_spare_part_product_count(self): + if not self: + return + # Raw SQL for performance: the ORM approach triggers one query per + # record which is too slow on large recordsets + self.env.cr.execute( + "SELECT spare_part_id, COUNT(*)" + " FROM lighting_product_spare_part_rel" + " WHERE spare_part_id IN %s" + " GROUP BY spare_part_id", + (tuple(self.ids),), + ) + counts = dict(self.env.cr.fetchall()) + for rec in self: + rec.parent_spare_part_product_count = counts.get(rec.id, 0) + + is_spare_part = fields.Boolean( + string="Is spare part", + compute="_compute_is_spare_part", + search="_search_is_spare_part", + ) + + @api.depends("spare_part_ids") + def _compute_is_spare_part(self): + if not self: + return + # Raw SQL for performance: the ORM approach triggers one query per + # record which is too slow on large recordsets + self.env.cr.execute( + "SELECT DISTINCT spare_part_id" + " FROM lighting_product_spare_part_rel" + " WHERE spare_part_id IN %s", + (tuple(self.ids),), + ) + spare_ids = {row[0] for row in self.env.cr.fetchall()} + for rec in self: + rec.is_spare_part = rec.id in spare_ids + + def _search_is_spare_part(self, operator, value): + ids = ( + self.env["lighting.product"] + .search([("spare_part_ids", "!=", False)]) + .mapped("spare_part_ids.id") + ) + return [("id", "in", ids)] + # logistics tab tariff_item = fields.Char( tracking=True, @@ -1553,7 +1613,7 @@ def _check_composite_product(self): ) ) - @api.constrains("optional_ids", "required_ids") + @api.constrains("optional_ids", "required_ids", "spare_part_ids") def _check_product_dependency(self): for rec in self: if rec in rec.required_ids: @@ -1566,6 +1626,10 @@ def _check_product_dependency(self): "The current reference cannot be defined as a recomended accessory" ) ) + if rec in rec.spare_part_ids: + raise ValidationError( + _("The current reference cannot be defined as a spare part") + ) # TODO: REVIEW: Self ensure @api.constrains("product_group_id") diff --git a/lighting/views/product_views.xml b/lighting/views/product_views.xml index 153b2966..2c346f25 100644 --- a/lighting/views/product_views.xml +++ b/lighting/views/product_views.xml @@ -30,6 +30,18 @@

Create the first product

+ + Parent products as spare parts + lighting.product + tree,kanban,form + [('spare_part_ids', '=', active_id)] + {'default_spare_part_ids': [(4, active_id, False)]} + +

Create the first product

+
+
product.form lighting.product @@ -73,6 +85,20 @@ widget="statinfo" /> +