From fa9782d24d95a4b3d04a04a63ed220f0b60daeda Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Mon, 18 Jul 2016 02:13:50 +0200 Subject: [PATCH] [FIX] website_sale: avoid caching browse_records The migration of `website_sale` to the new API at revision 788c1334e2cbe26fa26d4c6d4974dc413dbff608 repeated this problem initially fixed by PR #8795. A browse_record returned by a cached method will be broken at the next use, because it is bound to a closed cursor. The symptom is weird exception in the middle of a future request: ```OperationalError: Unable to use a closed cursor.``` (which refers to an old cached cursor, not the cursor of the current request!) Solution: workaround the problem by returning IDs in the method that needs to be cached (`_get_pl_partner_order`), and re-browse them as needed in caller methods. In addition, remove the useless extra caching of `_get_pl`, as all it does is browse() the result of the former method, and that would trigger the very same bug again. --- addons/website_sale/models/sale_order.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py index 35295ab1cd0..f04882bb902 100644 --- a/addons/website_sale/models/sale_order.py +++ b/addons/website_sale/models/sale_order.py @@ -146,6 +146,7 @@ class Website(models.Model): for website in self: website.pricelist_id = website.with_context(website_id=website.id).get_current_pricelist() + # This method is cached, must not return records! See also #8795 @tools.ormcache('self.env.uid', 'country_code', 'show_visible', 'website_pl', 'current_pl', 'all_pl', 'partner_pl', 'order_pl') def _get_pl_partner_order(self, country_code, show_visible, website_pl, current_pl, all_pl, partner_pl=False, order_pl=False): """ Return the list of pricelists that can be used on website for the current user. @@ -173,11 +174,12 @@ class Website(models.Model): if not pricelists or partner.property_product_pricelist.id != website_pl: pricelists |= partner.property_product_pricelist - return pricelists.sorted(lambda pl: pl.name) + # This method is cached, must not return records! See also #8795 + return pricelists.sorted(lambda pl: pl.name).ids - @tools.ormcache('self.env.uid', 'country_code', 'show_visible', 'website_pl', 'current_pl', 'all_pl') def _get_pl(self, country_code, show_visible, website_pl, current_pl, all_pl): - return self._get_pl_partner_order(country_code, show_visible, website_pl, current_pl, all_pl) + pl_ids = self._get_pl_partner_order(country_code, show_visible, website_pl, current_pl, all_pl) + return self.env['product.pricelist'].browse(pl_ids) def get_pricelist_available(self, show_visible=False): @@ -202,7 +204,7 @@ class Website(models.Model): website.website_pricelist_ids, partner_pl=partner_pl and partner_pl.id or None, order_pl=order_pl and order_pl.id or None) - return pricelists + return self.env['product.pricelist'].browse(pricelists) def is_pricelist_available(self, pl_id): """ Return a boolean to specify if a specific pricelist can be manually set on the website. @@ -401,7 +403,6 @@ class WebsitePricelist(models.Model): # list of available pricelists. So, we need to invalidate the cache when # we change the config of website price list to force to recompute. website = self.env['website'] - website._get_pl.clear_cache(website) website._get_pl_partner_order.clear_cache(website) @api.multi