From 9f0120d73bbbc364d8ec04b0e3ad63c75086ba52 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Wed, 24 Feb 2016 18:21:19 +0100 Subject: [PATCH 1/6] [FIX] point_of_sale: Sales Details timezone The Sales Details report wizard gives the possibility to print the details of the POS orders between two dates. The fields in the wizard are of type `date`, while the orders dates are of type `datetime`. `00:00:00` and `23:59:59` were naively added to the `date_start` and `date_end` (respectively) to handle the case. But, this doesn't take care of the user time zone: When a user choose between February 24th and February 25th, it's within his time zone, and therefore, for the search, where the datetime are in UTC, adding `00:00:00` isn't enough, the dates have to be converted from the user time zone to UTC. opw-6698831 --- addons/point_of_sale/report/pos_details.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/addons/point_of_sale/report/pos_details.py b/addons/point_of_sale/report/pos_details.py index 3416c6f879d..ddf88763873 100644 --- a/addons/point_of_sale/report/pos_details.py +++ b/addons/point_of_sale/report/pos_details.py @@ -19,7 +19,10 @@ # ############################################################################## +import datetime +import pytz import time +from openerp import tools from openerp.report import report_sxw class pos_details(report_sxw.rml_parse): @@ -44,7 +47,22 @@ class pos_details(report_sxw.rml_parse): result = {} user_ids = form['user_ids'] or self._get_all_users() company_id = user_obj.browse(self.cr, self.uid, self.uid).company_id.id - pos_ids = pos_obj.search(self.cr, self.uid, [('date_order','>=',form['date_start'] + ' 00:00:00'),('date_order','<=',form['date_end'] + ' 23:59:59'),('user_id','in',user_ids),('state','in',['done','paid','invoiced']),('company_id','=',company_id)]) + user = self.pool['res.users'].browse(self.cr, self.uid, self.uid) or self.localcontext.get('tz') or 'UTC' + tz_name = user.tz + user_tz = pytz.timezone(tz_name) + between_dates = {} + for date_field, delta in {'date_start': {'days': 0}, 'date_end': {'days': 1}}.items(): + timestamp = datetime.datetime.strptime(form[date_field] + ' 00:00:00', tools.DEFAULT_SERVER_DATETIME_FORMAT) + datetime.timedelta(**delta) + timestamp = user_tz.localize(timestamp).astimezone(pytz.utc) + between_dates[date_field] = timestamp.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT) + + pos_ids = pos_obj.search(self.cr, self.uid, [ + ('date_order', '>=', between_dates['date_start']), + ('date_order', '<', between_dates['date_end']), + ('user_id', 'in', user_ids), + ('state', 'in', ['done', 'paid', 'invoiced']), + ('company_id', '=', company_id) + ]) for pos in pos_obj.browse(self.cr, self.uid, pos_ids): for pol in pos.lines: result = { From 9ecd80eaeb28880e989eee10e1a543746e46f036 Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Mon, 1 Feb 2016 16:37:57 +0100 Subject: [PATCH 2/6] [FIX] website: sitemap fix length Iterator was consuming the first 45k records. So don't need to specify an offset, because that will ignore the next 45k. Eg: if step of 5, and range(1,13), it will only use [1, 2, 3, 4, 5, 11, 12, 13] Cherry-pick/backport of de8296c3a86da5e4ae35edcdb563d317dac32e76 --- addons/website/controllers/main.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py index 3862d19f0f8..731b7488200 100644 --- a/addons/website/controllers/main.py +++ b/addons/website/controllers/main.py @@ -122,9 +122,8 @@ class Website(openerp.addons.web.controllers.main.Home): first_page = None locs = request.website.sudo(user=request.website.user_id.id).enumerate_pages() while True: - start = pages * LOC_PER_SITEMAP values = { - 'locs': islice(locs, start, start + LOC_PER_SITEMAP), + 'locs': islice(locs, 0, LOC_PER_SITEMAP), 'url_root': request.httprequest.url_root[:-1], } urls = iuv.render(cr, uid, 'website.sitemap_locs', values, context=context) From 0eb9772ab8256e341b32537c88dfcc9d0367f9a7 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Thu, 25 Feb 2016 15:13:00 +0100 Subject: [PATCH 3/6] [FIX] calendar: rrule computation of private events If an event is private, a bunch of fields are hidden for the users not being the owner of the event, even for sudo. The fields on which depends the `rrule` computation were part of the hidden/private fields. In addition, the `rrule` is always computed as sudo. See `_get_rulestring`. Therefore, the `rrule` of recurrent private events was not correctly computed when the owner wasn't the administrator. opw-670295 --- addons/calendar/calendar.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/calendar/calendar.py b/addons/calendar/calendar.py index 0ef87d362c2..3b067a0f66e 100644 --- a/addons/calendar/calendar.py +++ b/addons/calendar/calendar.py @@ -1708,7 +1708,9 @@ class calendar_event(osv.Model): continue if r['class'] == 'private': for f in r.keys(): - if f not in ('id', 'allday', 'start', 'stop', 'duration', 'user_id', 'state', 'interval', 'count', 'recurrent_id_date', 'rrule'): + recurrent_fields = self._get_recurrent_fields(cr, uid, context=context) + public_fields = list(set(recurrent_fields + ['id', 'allday', 'start', 'stop', 'duration', 'user_id', 'state', 'interval', 'count', 'recurrent_id_date', 'rrule'])) + if f not in public_fields: if isinstance(r[f], list): r[f] = [] else: From cfcf8bb31866b223e97a7ced60e425e1c1cbab4f Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Thu, 25 Feb 2016 17:01:10 +0100 Subject: [PATCH 4/6] [FIX] product: avoid traceback when product had no variant. Compute price with a product template without product product raises a traceback: index out of tuple --- addons/product/pricelist.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/product/pricelist.py b/addons/product/pricelist.py index 69df14f0cb1..4f79a438462 100644 --- a/addons/product/pricelist.py +++ b/addons/product/pricelist.py @@ -277,8 +277,7 @@ class product_pricelist(osv.osv): if is_product_template: if rule.product_tmpl_id and product.id != rule.product_tmpl_id.id: continue - if rule.product_id and \ - (product.product_variant_count > 1 or product.product_variant_ids[0].id != rule.product_id.id): + if rule.product_id and not (product.product_variant_count == 1 and product.product_variant_ids[0].id == rule.product_id.id): # product rule acceptable on template if has only one variant continue else: From 1d269d20f25d29a791bedabc39cdf865215c9887 Mon Sep 17 00:00:00 2001 From: Anton Chepurov Date: Thu, 25 Feb 2016 17:55:29 +0200 Subject: [PATCH 5/6] [FIX] website: sitemap scalability Checking url_list for duplicates is O(n). Use url_set instead of url_list to improve to O(1). Otherwise sitemap generation even for a million products will never finish. Close #11106 --- addons/website/models/website.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/website/models/website.py b/addons/website/models/website.py index 8aee2add5c0..1d5ffd26f7d 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -384,7 +384,7 @@ class website(osv.osv): """ router = request.httprequest.app.get_db_router(request.db) # Force enumeration to be performed as public user - url_list = [] + url_set = set() for rule in router.iter_rules(): if not self.rule_is_enumerable(rule): continue @@ -416,9 +416,9 @@ class website(osv.osv): page[key[2:]] = val if url in ('/sitemap.xml',): continue - if url in url_list: + if url in url_set: continue - url_list.append(url) + url_set.add(url) yield page From 45d4bd04cb5152e20f6e4c63aaefa240ed7104b9 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Tue, 26 Jan 2016 17:04:39 +0100 Subject: [PATCH 6/6] [FIX] purchase: the stock should be valued without the taxes included from the purchase order line From issue 660592. (already fixed in v9) When products are received from a purchase line with taxes included, the cost for the stock valuation (on the stock move) on reception should be without these taxes included. --- addons/purchase/purchase.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 8413cbfe702..e55d9ff98df 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -747,6 +747,10 @@ class purchase_order(osv.osv): ''' prepare the stock move data from the PO line. This function returns a list of dictionary ready to be used in stock.move's create()''' product_uom = self.pool.get('product.uom') price_unit = order_line.price_unit + if order_line.taxes_id: + taxes = self.pool['account.tax'].compute_all(cr, uid, order_line.taxes_id, price_unit, 1.0, + order_line.product_id, order.partner_id) + price_unit = taxes['total'] if order_line.product_uom.id != order_line.product_id.uom_id.id: price_unit *= order_line.product_uom.factor / order_line.product_id.uom_id.factor if order.currency_id.id != order.company_id.currency_id.id: