Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[15.0][FIX] product_assortment: Product black_list_domain invalidates whitelist_product_ids. New cache methods to performance #1343

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion product_assortment/__manifest__.py
Original file line number Diff line number Diff line change
@@ -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).

{
Expand All @@ -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,
}
33 changes: 33 additions & 0 deletions product_assortment/data/ir_cron.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo noupdate="1">
<!-- Force to recompute all partners to take into account changes in related partner fields models.
P.E.: Domain includes tag_ids.name contains "**" and user changes tag name from tags view -->
<record
id="action_product_assortment_recompute_all_partners"
model="ir.actions.server"
>
<field name="name">Product assortment recompute all partbers</field>
<field name="model_id" ref="model_ir_filters" />
<field name="binding_model_id" ref="model_ir_filters" />
<field name="state">code</field>
<field name="code">model.search([])._compute_all_partner_ids()</field>
</record>

<!-- Cron to recompute all partners. (Not active by default). -->
<record id="ir_cron_product_assortment_recompute_all_partners" model="ir.cron">
carlosdauden marked this conversation as resolved.
Show resolved Hide resolved
<field
name="ir_actions_server_id"
ref="action_product_assortment_recompute_all_partners"
/>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False" />
<field name="active" eval="False" />
<field
name="nextcall"
eval="(DateTime.now().replace(hour=3, minute=0, second=0) + timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S')"
/>
</record>

</odoo>
13 changes: 10 additions & 3 deletions product_assortment/i18n/es.po
Original file line number Diff line number Diff line change
Expand Up @@ -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 <sergio.teruel@tecnativa.com>\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 <carlos.dauden@tecnativa.com>\n"
"Language-Team: \n"
"Language: es\n"
"MIME-Version: 1.0\n"
Expand Down Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions product_assortment/i18n/product_assortment.pot
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
34 changes: 25 additions & 9 deletions product_assortment/models/ir_filters.py
Original file line number Diff line number Diff line change
@@ -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


Expand Down Expand Up @@ -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"""
Expand All @@ -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,
Expand All @@ -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):
Expand Down Expand Up @@ -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"
Expand Down
37 changes: 36 additions & 1 deletion product_assortment/models/res_partner.py
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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