From 08b75b7bcb4506342ef3e9525dc4d3e68abfb410 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 9 Aug 2017 16:34:44 +0200 Subject: [PATCH 1/5] [FIX] pad: do not crash during record creation Backport of 0de067cae919937cfc5fa4cd3161d58f48d472b5 (and 9b8bc5e5a11d625a72043e2b076d99be3c24d2c4) Rev. c5bd50927441ba98ae99d56ff765111cf4f6d2f3 attempted to improve the pad sync mechanism when merging records (tasks), but failed to consider the case where the pad_url field is not set yet. This happens at create(), due to the chicken-and-egg problem with the pad URL depending on the record ID, and therefore set *after* creation. Ignoring the sync when the URL is not yet set should be enough, as the URL generation method also takes care of that first sync. --- addons/pad/models/pad.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/pad/models/pad.py b/addons/pad/models/pad.py index eb6267ee389..65a8bf5bc5f 100644 --- a/addons/pad/models/pad.py +++ b/addons/pad/models/pad.py @@ -117,7 +117,7 @@ class PadCommon(models.AbstractModel): def _set_pad_value(self, vals): # Update the pad if the `pad_content_field` is modified for k, field in self._fields.iteritems(): - if hasattr(field, 'pad_content_field') and vals.get(field.pad_content_field): + if hasattr(field, 'pad_content_field') and vals.get(field.pad_content_field) and self[k]: company = self.env.user.sudo().company_id myPad = EtherpadLiteClient(company.pad_key, company.pad_server + '/api') path = self[k].split('/p/')[1] From ac392096d882529e0ab8ae0658181814037a197b Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Thu, 10 Aug 2017 09:00:59 +0200 Subject: [PATCH 2/5] [FIX] stock: recompute display name The display name of a location should be recomputed when the name of the parent location is changed. opw-761463 --- addons/stock/models/stock_location.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/stock/models/stock_location.py b/addons/stock/models/stock_location.py index 1c53851999f..eb88b140a1b 100644 --- a/addons/stock/models/stock_location.py +++ b/addons/stock/models/stock_location.py @@ -69,7 +69,7 @@ class Location(models.Model): _sql_constraints = [('barcode_company_uniq', 'unique (barcode,company_id)', 'The barcode for a location must be unique per company !')] @api.one - @api.depends('name', 'location_id') + @api.depends('name', 'location_id.name') def _compute_complete_name(self): """ Forms complete name of location from parent location to child location. """ name = self.name From 1aed433f54cdc34c9a1e4e35d98162869a123acc Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Wed, 9 Aug 2017 16:19:27 +0200 Subject: [PATCH 3/5] [FIX] website_event: Website Event Error when you encode a 0 value in the registration The function registration_new must return a type json. opw:765643 --- addons/website_event/controllers/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/website_event/controllers/main.py b/addons/website_event/controllers/main.py index 6bf3801a961..6df93deca78 100644 --- a/addons/website_event/controllers/main.py +++ b/addons/website_event/controllers/main.py @@ -253,7 +253,7 @@ class website_event(http.Controller): def registration_new(self, event, **post): tickets = self._process_tickets_details(post) if not tickets: - return request.redirect("/event/%s" % slug(event)) + return False return request.website._render("website_event.registration_attendee_details", {'tickets': tickets, 'event': event}) def _process_registration_details(self, details): From 354539942d29acc4cfefdb8851ed18ff1bdd4b63 Mon Sep 17 00:00:00 2001 From: Nicolas Lempereur Date: Thu, 10 Aug 2017 11:17:47 +0200 Subject: [PATCH 4/5] [FIX] website_sale: no-cache IE11 cached cart XHR IE11 seems to be always using cache when doin an XHR request with the same GET request. It can be changed in several ways: - returning a header: "Cache-Control: no-cache" - altering the GET request with a nonce - using the POST method instead of GET to solve it, in this change the HTTP header is added on the response. opw-752270 closes #18787 --- addons/website_sale/controllers/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index 6273be817ca..daeb403f95b 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -357,7 +357,8 @@ class WebsiteSale(http.Controller): values['suggested_products'] = _order._cart_accessories() if post.get('type') == 'popover': - return request.render("website_sale.cart_popover", values) + # force no-cache so IE11 doesn't cache this XHR + return request.render("website_sale.cart_popover", values, headers={'Cache-Control': 'no-cache'}) if post.get('code_not_available'): values['code_not_available'] = post.get('code_not_available') From d140f0ef0e7d9cb3eb4a6ad344ae761936a0a288 Mon Sep 17 00:00:00 2001 From: xmo-odoo Date: Thu, 10 Aug 2017 14:51:27 +0200 Subject: [PATCH 5/5] [FIX] prefetch issues on computed/related fields (#18644) When deciding to prefetch records (getting records from the cache with no value for the field being fetched), if the field was computed `determine_value` would just get all records, not limited by the normal prefetch limit; for large recordsets this would generate gigantic prefetch lists for records we may not need at all. Fix by applying the `PREFETCH_MAX` limit to records from the cache as is done in `_prefetch_field`. Complementarily, when traversing related fields the prefetch environment would be lost and every record would get an empty prefetch environment, so the values would ultimately be read one by one. Example: select (search) 1000 product.product records, access a related field (e.g. categ_id) in a loop, on the first iteration the system would first read 1000 templates, then it would read each categ_id individually, resulting in >1000 SQL queries rather than the ~2 we would expect. Fixes #18511 --- odoo/fields.py | 3 ++- odoo/models.py | 17 ++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/odoo/fields.py b/odoo/fields.py index ee9547ca774..745e5effb62 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -565,7 +565,7 @@ class Field(object): """ Traverse the fields of the related field `self` except for the last one, and return it as a pair `(last_record, last_field)`. """ for name in self.related[:-1]: - record = record[name][:1] + record = record[name][:1].with_prefetch(record._prefetch) return record, self.related_field def _compute_related(self, records): @@ -978,6 +978,7 @@ class Field(object): self.compute_value(record) else: recs = record._in_cache_without(self) + recs = recs.with_prefetch(record._prefetch) self.compute_value(recs) else: diff --git a/odoo/models.py b/odoo/models.py index 5eeef77ef4e..f58ed393eb2 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -3058,10 +3058,6 @@ class BaseModel(object): else: records &= self._in_cache_without(f) - # prefetch at most PREFETCH_MAX records - if len(records) > PREFETCH_MAX: - records = records[:PREFETCH_MAX] | self - # fetch records with read() assert self in records and field in fs records = records.with_prefetch(self._prefetch) @@ -5232,13 +5228,16 @@ class BaseModel(object): return RecordCache(self) @api.model - def _in_cache_without(self, field): - """ Make sure ``self`` is present in cache (for prefetching), and return - the records of model ``self`` in cache that have no value for ``field`` - (:class:`Field` instance). + def _in_cache_without(self, field, limit=PREFETCH_MAX): + """ Return records to prefetch that have no value in cache for ``field`` + (:class:`Field` instance), including ``self``. + Return at most ``limit`` records. """ ids = filter(None, self._prefetch[self._name] - set(self.env.cache[field])) - return self.browse(ids) + recs = self.browse(ids) + if limit and len(recs) > limit: + recs = self + (recs - self)[:(limit - len(self))] + return recs @api.model def refresh(self):