diff --git a/product_assortment/__manifest__.py b/product_assortment/__manifest__.py index ffa756fc72b0..60e89fee6f29 100644 --- a/product_assortment/__manifest__.py +++ b/product_assortment/__manifest__.py @@ -1,4 +1,5 @@ # Copyright 2021 ACSONE SA/NV +# Copyright 2023 Tecnativa - Carlos Dauden # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { @@ -11,6 +12,10 @@ "author": "ACSONE SA/NV,Odoo Community Association (OCA)", "website": "https://github.com/OCA/product-attribute", "depends": ["base", "product"], - "data": ["views/product_assortment.xml", "views/res_partner_view.xml"], + "data": [ + "data/ir_cron.xml", + "views/product_assortment.xml", + "views/res_partner_view.xml", + ], "installable": True, } diff --git a/product_assortment/data/ir_cron.xml b/product_assortment/data/ir_cron.xml new file mode 100644 index 000000000000..1315b9a1fca2 --- /dev/null +++ b/product_assortment/data/ir_cron.xml @@ -0,0 +1,33 @@ + + + + + Product assortment recompute all partbers + + + code + model.search([])._compute_all_partner_ids() + + + + + + 1 + days + -1 + + + + + + diff --git a/product_assortment/i18n/es.po b/product_assortment/i18n/es.po index 41b22e69837d..1709e8e1e8eb 100644 --- a/product_assortment/i18n/es.po +++ b/product_assortment/i18n/es.po @@ -6,9 +6,9 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 13.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-19 05:53+0000\n" -"PO-Revision-Date: 2022-07-19 07:55+0200\n" -"Last-Translator: Sergio Teruel \n" +"POT-Creation-Date: 2023-03-06 11:12+0000\n" +"PO-Revision-Date: 2023-03-06 12:14+0100\n" +"Last-Translator: Carlos Dauden \n" "Language-Team: \n" "Language: es\n" "MIME-Version: 1.0\n" @@ -109,6 +109,13 @@ msgstr "Surtido de producto" msgid "Product assortment" msgstr "Surtido de producto" +#. module: product_assortment +#: model:ir.actions.server,name:product_assortment.action_product_assortment_invalidate_cache +#: model:ir.cron,cron_name:product_assortment.ir_cron_product_assortment_invalidate_cache +#: model:ir.cron,name:product_assortment.ir_cron_product_assortment_invalidate_cache +msgid "Product assortment reset cache" +msgstr "Resetear cache de surtido de producto" + #. module: product_assortment #: code:addons/product_assortment/models/ir_filters.py:0 #, python-format diff --git a/product_assortment/i18n/product_assortment.pot b/product_assortment/i18n/product_assortment.pot index d4aa4a16f460..a2b0a2c23315 100644 --- a/product_assortment/i18n/product_assortment.pot +++ b/product_assortment/i18n/product_assortment.pot @@ -105,6 +105,13 @@ msgstr "" msgid "Product assortment" msgstr "" +#. module: product_assortment +#: model:ir.actions.server,name:product_assortment.action_product_assortment_invalidate_cache +#: model:ir.cron,cron_name:product_assortment.ir_cron_product_assortment_invalidate_cache +#: model:ir.cron,name:product_assortment.ir_cron_product_assortment_invalidate_cache +msgid "Product assortment reset cache" +msgstr "" + #. module: product_assortment #: code:addons/product_assortment/models/ir_filters.py:0 #, python-format diff --git a/product_assortment/models/ir_filters.py b/product_assortment/models/ir_filters.py index 2deb6d7b12ec..1d015e35c65b 100644 --- a/product_assortment/models/ir_filters.py +++ b/product_assortment/models/ir_filters.py @@ -1,8 +1,10 @@ # Copyright 2021 ACSONE SA/NV +# Copyright 2023 Tecnativa - Carlos Dauden # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import _, api, fields, models from odoo.osv import expression +from odoo.tools import ormcache from odoo.tools.safe_eval import datetime, safe_eval @@ -74,6 +76,17 @@ def create(self, vals_list): string="Restricted product domain", default="[]", required=True ) + @api.model + @ormcache() + def get_partner_domain_fields(self): + field_set = set() + for ir_filter in self.sudo().search([("is_assortment", "=", True)]): + domain = ir_filter._get_eval_partner_domain() + for item in domain: + if isinstance(item, (list, tuple)) and isinstance(item[0], str): + field_set.add(item[0].split(".")[0]) + return field_set + @api.depends("partner_ids", "partner_domain") def _compute_all_partner_ids(self): """Summarize selected partners and partners from partner domain field""" @@ -90,15 +103,6 @@ def _compute_all_partner_ids(self): def _get_eval_domain(self): res = super()._get_eval_domain() - - if self.whitelist_product_ids: - result_domain = [("id", "in", self.whitelist_product_ids.ids)] - res = expression.OR([result_domain, res]) - - if self.blacklist_product_ids: - result_domain = [("id", "not in", self.blacklist_product_ids.ids)] - res = expression.AND([result_domain, res]) - if self.apply_black_list_product_domain: black_list_domain = safe_eval( self.black_list_product_domain, @@ -107,6 +111,12 @@ def _get_eval_domain(self): res = expression.AND( [expression.distribute_not(["!"] + black_list_domain), res] ) + if self.whitelist_product_ids: + result_domain = [("id", "in", self.whitelist_product_ids.ids)] + res = expression.OR([result_domain, res]) + if self.blacklist_product_ids: + result_domain = [("id", "not in", self.blacklist_product_ids.ids)] + res = expression.AND([result_domain, res]) return res def _get_eval_black_list_domain(self): @@ -144,6 +154,12 @@ def _get_action_domain(self, action_id=None): return domain + def write(self, vals): + res = super().write(vals) + if "partner_ids" in vals or "partner_domain" in vals: + self.clear_caches() + return res + def show_products(self): self.ensure_one() xmlid = "product.product_normal_action_sell" diff --git a/product_assortment/models/res_partner.py b/product_assortment/models/res_partner.py index d1da9ea5e643..dd6721400cd9 100644 --- a/product_assortment/models/res_partner.py +++ b/product_assortment/models/res_partner.py @@ -1,11 +1,19 @@ # Copyright 2021 Tecnativa - Carlos Roca +# Copyright 2021 Tecnativa - Carlos Dauden # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). -from odoo import models +from odoo import api, fields, models class ResPartner(models.Model): _inherit = "res.partner" + applied_assortment_ids = fields.Many2many( + comodel_name="ir.filters", + relation="ir_filter_all_partner_rel", + column1="partner_id", + column2="filter_id", + ) + def action_define_product_assortment(self): self.ensure_one() xmlid = "product_assortment.actions_product_assortment_view" @@ -24,3 +32,30 @@ def action_define_product_assortment(self): ) action["context"] = ctx return action + + def _update_partner_assortments(self): + # Using sudo to contemplate evaluation of domains with restricted fields + self = self.sudo() + assortments = self.env["ir.filters"].search([("is_assortment", "=", True)]) + for partner in self: + # Use ids instead of record to improve performance (Remove in next versions) + partner_assortment_ids = [] + for assortment in assortments: + if partner in assortment.partner_ids or partner.filtered_domain( + assortment._get_eval_partner_domain() + ): + partner_assortment_ids.append(assortment.id) + partner.applied_assortment_ids = assortments.browse(partner_assortment_ids) + + @api.model_create_multi + def create(self, vals_list): + partners = super().create(vals_list) + self._update_partner_assortments() + return partners + + def write(self, vals): + res = super().write(vals) + IrFilters = self.env["ir.filters"] + if IrFilters.get_partner_domain_fields() & set(vals.keys()): + self._update_partner_assortments() + return res