From 3d1fe33a362422b3df8ece8b94a896379c3f4071 Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Thu, 8 Jun 2017 10:17:01 +0200 Subject: [PATCH 01/12] [FIX] calendar: _get_recurrent_date_by_event Let's create in google calendar a reccurent event with all day set and a end date. When synchronising google calendar with Odoo(by clicking on button "Sync with Google"). It raised on error because the start date had a time zone but not the end date(the UNTIL in the rrule). Fine tuning of 20ed57f874176161a043dee834b25c7f0b3dc175 opw:746549 --- addons/calendar/models/calendar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py index 8c18fe2e24b..145614fc045 100644 --- a/addons/calendar/models/calendar.py +++ b/addons/calendar/models/calendar.py @@ -553,7 +553,7 @@ class Meeting(models.Model): if not event_date: event_date = datetime.now() - if self.allday and self.rrule and 'Z' not in self.rrule: + if self.allday and self.rrule and 'UNTIL' in self.rrule and 'Z' not in self.rrule: rset1 = rrule.rrulestr(str(self.rrule), dtstart=event_date.replace(tzinfo=None), forceset=True, ignoretz=True) else: # Convert the event date to saved timezone (or context tz) as it'll From b4863378efa6a30acc507fd05dc977195c3ff254 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Thu, 8 Jun 2017 10:23:37 +0200 Subject: [PATCH 02/12] [FIX] website, website_sale: product website price and pricelist without request Attempting to read the field `website_price` directly with the XMLRPC API failed because, in such a case, the request is unbound, and attempting to read anything from it (`request.session` whatever) resulted to the raise of an exception. e.g. This prevented to perform a `search_read` with all fields on the `product.product` model Closes #14939 opw-745733 --- addons/website/models/website.py | 5 +++-- addons/website_sale/models/sale_order.py | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/addons/website/models/website.py b/addons/website/models/website.py index 0a64d587bcb..6145fe13132 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -392,9 +392,10 @@ class Website(models.Model): @api.model def get_current_website(self): - domain_name = request.httprequest.environ.get('HTTP_HOST', '').split(':')[0] + domain_name = request and request.httprequest.environ.get('HTTP_HOST', '').split(':')[0] or None website_id = self._get_current_website_id(domain_name) - request.context = dict(request.context, website_id=website_id) + if request: + request.context = dict(request.context, website_id=website_id) return self.browse(website_id) @tools.cache('domain_name') diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py index 59b6432e3a6..6f31edc7a68 100644 --- a/addons/website_sale/models/sale_order.py +++ b/addons/website_sale/models/sale_order.py @@ -244,19 +244,19 @@ class Website(models.Model): :param bool show_visible: if True, we don't display pricelist where selectable is False (Eg: Code promo) :returns: pricelist recordset """ - website = request.website - if not request.website: + website = request and request.website or None + if not website: if self.env.context.get('website_id'): website = self.browse(self.env.context['website_id']) else: website = self.search([], limit=1) - isocountry = request.session.geoip and request.session.geoip.get('country_code') or False + isocountry = request and request.session.geoip and request.session.geoip.get('country_code') or False partner = self.env.user.partner_id order_pl = partner.last_website_so_id and partner.last_website_so_id.state == 'draft' and partner.last_website_so_id.pricelist_id partner_pl = partner.property_product_pricelist pricelists = website._get_pl_partner_order(isocountry, show_visible, website.user_id.sudo().partner_id.property_product_pricelist.id, - request.session.get('website_sale_current_pl'), + request and request.session.get('website_sale_current_pl') or None, website.pricelist_ids, partner_pl=partner_pl and partner_pl.id or None, order_pl=order_pl and order_pl.id or None) @@ -280,7 +280,7 @@ class Website(models.Model): available_pricelists = self.get_pricelist_available() pl = None partner = self.env.user.partner_id - if request.session.get('website_sale_current_pl'): + if request and request.session.get('website_sale_current_pl'): # `website_sale_current_pl` is set only if the user specifically chose it: # - Either, he chose it from the pricelist selection # - Either, he entered a coupon code From 11d6b5e15e812b81d3b136113ab8278137fe01b0 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Thu, 8 Jun 2017 11:13:20 +0200 Subject: [PATCH 03/12] [FIX] account: name search on journal with negative operators In the journal items, when performing a search "Journal" "Doesn't contain" "Something" Both its name AND its code must not contain "Something". Therefore, with negative operator, the domain must not be built with a OR connector but with an AND. Same thing goes for "is equal" and "is not equal". opw-726029 --- addons/account/models/account.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/addons/account/models/account.py b/addons/account/models/account.py index cf4d47a7425..6a2e73160bd 100644 --- a/addons/account/models/account.py +++ b/addons/account/models/account.py @@ -510,7 +510,10 @@ class AccountJournal(models.Model): @api.model def name_search(self, name='', args=None, operator='ilike', limit=100): args = args or [] - recs = self.search(['|', ('code', operator, name), ('name', operator, name)] + args, limit=limit) + connector = '|' + if operator in expression.NEGATIVE_TERM_OPERATORS: + connector = '&' + recs = self.search([connector, ('code', operator, name), ('name', operator, name)] + args, limit=limit) return recs.name_get() @api.multi From 8052869b19aaf2105713e0a8ba0555ca25dc26ef Mon Sep 17 00:00:00 2001 From: nafex Date: Tue, 6 Jun 2017 15:25:42 +0200 Subject: [PATCH 04/12] [FIX] delivery: create_price_rules won't create unnecessary rules anymore When updating a carrier that is not "fixed" or "base_on_rule", this method was creating unnecessary delivery.price.rule at each write. This patch fixes this issue. Closes PR #17443 --- addons/delivery/models/delivery_carrier.py | 40 +++++++++++----------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/addons/delivery/models/delivery_carrier.py b/addons/delivery/models/delivery_carrier.py index dad4e8a315f..fa46ef9b5f3 100644 --- a/addons/delivery/models/delivery_carrier.py +++ b/addons/delivery/models/delivery_carrier.py @@ -201,26 +201,26 @@ class DeliveryCarrier(models.Model): if record.delivery_type == 'fixed': PriceRule.search([('carrier_id', '=', record.id)]).unlink() - line_data = { - 'carrier_id': record.id, - 'variable': 'price', - 'operator': '>=', - } - # Create the delivery price rules - if record.free_if_more_than: - line_data.update({ - 'max_value': record.amount, - 'standard_price': 0.0, - 'list_base_price': 0.0, - }) - PriceRule.create(line_data) - if record.fixed_price is not False: - line_data.update({ - 'max_value': 0.0, - 'standard_price': record.fixed_price, - 'list_base_price': record.fixed_price, - }) - PriceRule.create(line_data) + line_data = { + 'carrier_id': record.id, + 'variable': 'price', + 'operator': '>=', + } + # Create the delivery price rules + if record.free_if_more_than: + line_data.update({ + 'max_value': record.amount, + 'standard_price': 0.0, + 'list_base_price': 0.0, + }) + PriceRule.create(line_data) + if record.fixed_price is not False: + line_data.update({ + 'max_value': 0.0, + 'standard_price': record.fixed_price, + 'list_base_price': record.fixed_price, + }) + PriceRule.create(line_data) return True @api.model From 1612f2cdf797adb1e7639874c8d0138d0d939749 Mon Sep 17 00:00:00 2001 From: xmo-odoo Date: Thu, 8 Jun 2017 11:42:25 +0200 Subject: [PATCH 05/12] [FIX] website_forum: untranslatable strings OPW-746261 --- addons/website_forum/i18n/website_forum.pot | 41 ++++++++++++++++++++ addons/website_forum/views/website_forum.xml | 38 ++++++++++-------- 2 files changed, 63 insertions(+), 16 deletions(-) diff --git a/addons/website_forum/i18n/website_forum.pot b/addons/website_forum/i18n/website_forum.pot index effc13bfb14..1d4b4a567db 100644 --- a/addons/website_forum/i18n/website_forum.pot +++ b/addons/website_forum/i18n/website_forum.pot @@ -604,6 +604,7 @@ msgid "Bad Request" msgstr "" #. module: website_forum +#: model:ir.model.fields,field_description:website_forum.field_res_users_badge_ids #: model:ir.ui.view,arch_db:website_forum.badge #: model:ir.ui.view,arch_db:website_forum.header #: model:ir.ui.view,arch_db:website_forum.user_detail_full @@ -782,6 +783,7 @@ msgstr "" #. openerp-web #: code:addons/website_forum/static/src/xml/website_forum_share_templates.xml:46 #: selection:forum.post,state:0 +#: model:ir.ui.view,arch_db:website_forum.post_description_full #, python-format msgid "Close" msgstr "" @@ -883,6 +885,16 @@ msgstr "" msgid "Convert all answers to comments and vice versa" msgstr "" +#. module: website_forum +#: model:ir.ui.view,arch_db:website_forum.post_answers +msgid "Convert as a comment" +msgstr "" + +#. module: website_forum +#: model:ir.ui.view,arch_db:website_forum.post_comment +msgid "Convert as an answer" +msgstr "" + #. module: website_forum #: model:ir.model.fields,field_description:website_forum.field_forum_post_karma_accept msgid "Convert comment to answer" @@ -968,6 +980,12 @@ msgstr "" msgid "Default Post" msgstr "" +#. module: website_forum +#: model:ir.ui.view,arch_db:website_forum.post_answers +#: model:ir.ui.view,arch_db:website_forum.post_description_full +msgid "Delete" +msgstr "" + #. module: website_forum #: model:ir.model.fields,field_description:website_forum.field_forum_forum_karma_unlink_all msgid "Delete all posts" @@ -1038,6 +1056,8 @@ msgstr "" #. module: website_forum #: model:ir.ui.view,arch_db:website_forum.edit_post +#: model:ir.ui.view,arch_db:website_forum.post_answers +#: model:ir.ui.view,arch_db:website_forum.post_description_full msgid "Edit" msgstr "" @@ -1184,6 +1204,11 @@ msgstr "" msgid "First upvote" msgstr "" +#. module: website_forum +#: model:ir.ui.view,arch_db:website_forum.post_description_full +msgid "Flag" +msgstr "" + #. module: website_forum #: model:ir.model.fields,field_description:website_forum.field_forum_forum_karma_flag #: model:ir.model.fields,field_description:website_forum.field_forum_post_karma_flag @@ -1193,6 +1218,7 @@ msgstr "" #. module: website_forum #: selection:forum.post,state:0 #: model:ir.ui.view,arch_db:website_forum.moderation_queue +#: model:ir.ui.view,arch_db:website_forum.post_description_full msgid "Flagged" msgstr "" @@ -2012,6 +2038,11 @@ msgstr "" msgid "Re: %s" msgstr "" +#. module: website_forum +#: model:ir.ui.view,arch_db:website_forum.post_description_full +msgid "Reactivate" +msgstr "" + #. module: website_forum #: model:ir.ui.view,arch_db:website_forum.header msgid "Read Guidelines" @@ -2064,6 +2095,11 @@ msgstr "" msgid "Relevance Computation" msgstr "" +#. module: website_forum +#: model:ir.ui.view,arch_db:website_forum.post_description_full +msgid "Reopen" +msgstr "" + #. module: website_forum #: model:ir.ui.view,arch_db:website_forum.post_answers #: model:ir.ui.view,arch_db:website_forum.post_description_full @@ -2384,6 +2420,11 @@ msgstr "" msgid "This post is already flagged" msgstr "" +#. module: website_forum +#: model:ir.ui.view,arch_db:website_forum.post_description_full +msgid "This post is currently awaiting moderation and not yet published... Do you want Accept or Reject this post ?" +msgstr "" + #. module: website_forum #: model:ir.ui.view,arch_db:website_forum.private_profile msgid "This profile is private!" diff --git a/addons/website_forum/views/website_forum.xml b/addons/website_forum/views/website_forum.xml index 06692cc9b2b..5cfeef0670c 100644 --- a/addons/website_forum/views/website_forum.xml +++ b/addons/website_forum/views/website_forum.xml @@ -787,9 +787,10 @@
- - - + + + + By - + Reopen @@ -826,7 +827,7 @@
  • - + Reopen @@ -834,7 +835,7 @@
  • - + Edit @@ -842,7 +843,7 @@
  • - + Close @@ -850,7 +851,7 @@
  • - + Delete @@ -858,7 +859,7 @@
  • - + Reactivate @@ -866,7 +867,7 @@
  • - + Reactivate @@ -877,7 +878,12 @@ t-attf-data-karma="#{not question.can_flag and question.forum_id.karma_flag or 0}" t-attf-data-href="/forum/#{slug(forum)}/post/#{slug(question)}/flag" > - + + Flagged + + + Flag +
  • @@ -964,7 +970,7 @@
  • - + Edit @@ -972,7 +978,7 @@
  • - + Delete @@ -989,7 +995,7 @@
  • - + Convert as a comment @@ -1057,7 +1063,7 @@ - + @@ -1070,7 +1076,7 @@ - + Convert as an answer From c4c9347b9986f60f1b8a534b805e248b25e3eef8 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Thu, 8 Jun 2017 13:53:49 +0200 Subject: [PATCH 06/12] [IMP] web: Expose char_domain dialog widget This simple return allows submodules to be able to know when a dialog is shown and modify something in it. Note from GED: I am aware that this is a IMP in a stable version, and I really don't like that... But it looks like it really helps many people, as shown by the PR, and the risk induced by this commit is definitely extremely low, so I will make an exception. (PR: #15579) --- addons/web/static/src/js/views/form_widgets.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/web/static/src/js/views/form_widgets.js b/addons/web/static/src/js/views/form_widgets.js index 450025ee06b..70a11214901 100644 --- a/addons/web/static/src/js/views/form_widgets.js +++ b/addons/web/static/src/js/views/form_widgets.js @@ -501,6 +501,8 @@ var FieldCharDomain = common.AbstractField.extend(common.ReinitializeFieldMixin, } } }).open(); + this.trigger("dialog_opened", dialog); + return dialog; }, }); From 77be3d8b396f31adfa11d2cd10a22ee3a7f27883 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Wed, 7 Jun 2017 15:49:32 +0200 Subject: [PATCH 07/12] [FIX] account: avoid duplicated move name Commits 9365482df05 and 8fc81b871debc2 attempted to prevent the creation of two moves with the same name during reconciliation. It works in most cases, but it is still possible to reconcile the same statement line with more than one line. We add an extra check to make sure duplicate never happen. opw-742018 --- addons/account/models/account_bank_statement.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/addons/account/models/account_bank_statement.py b/addons/account/models/account_bank_statement.py index c9634d5f270..e49546e31e7 100644 --- a/addons/account/models/account_bank_statement.py +++ b/addons/account/models/account_bank_statement.py @@ -891,6 +891,10 @@ class AccountBankStatementLine(models.Model): # Create the move self.sequence = self.statement_id.line_ids.ids.index(self.id) + 1 move_name = (self.statement_id.name or self.name) + "/" + str(self.sequence) + # Ensure no duplicate is created + if self.env['account.move'].search([('name', '=', move_name)]): + count = self.env['account.move'].search_count([('name', '=like', move_name + '/%')]) + move_name = u'{}/{}'.format(move_name, count + 1) move_vals = self._prepare_reconciliation_move(move_name) move = self.env['account.move'].create(move_vals) counterpart_moves = (counterpart_moves | move) From 45e94ec756e0da4766110bd3ce94ede4203e4486 Mon Sep 17 00:00:00 2001 From: xmo-odoo Date: Thu, 8 Jun 2017 14:16:43 +0200 Subject: [PATCH 08/12] [FIX] web: CrashManager can crash if trying to show an empty message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If `d.message` is an empty string, `!!d.message` is false and the crashmanager will try to display `d.error.data.message`… which does not exist as it's a warning with an empty message not an upstream error. That causes the crashmanager itself to crash, and even the warning name/title to be lost. --- addons/web/static/src/xml/base.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index c846e969827..161509b364f 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -22,7 +22,7 @@
    - var message = d.message ? d.message : d.error.data.message; + var message = (d.message !== undefined) ? d.message : d.error.data.message; d.html_error = context.engine.tools.html_escape(message).replace(/\n/g, '
    ');
    From e79eaecc46d72187c8a7ad39c0f2b17b61dff267 Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Thu, 8 Jun 2017 15:37:55 +0200 Subject: [PATCH 09/12] [FIX] stock:Creating new lots when option "use only existing lots" is activated When the field use_create_lots is set to False in a picking type, it is not possible to create lot for a pack operation linked to this picking type. opw:744862 --- addons/stock/i18n/stock.pot | 6 ++++++ addons/stock/models/stock_production_lot.py | 10 ++++++++++ addons/stock/views/stock_pack_operation_views.xml | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/addons/stock/i18n/stock.pot b/addons/stock/i18n/stock.pot index e01b6291165..c257035f4a9 100644 --- a/addons/stock/i18n/stock.pot +++ b/addons/stock/i18n/stock.pot @@ -6596,6 +6596,12 @@ msgid "You cannot set a negative product quantity in an inventory line:\n" " %s - qty: %s" msgstr "" +#. module: stock +#: code:addons/stock/models/stock_production_lot.py:37 +#, python-format +msgid "You are not allowed to create a lot for this picking type" +msgstr "" + #. module: stock #: code:addons/stock/models/stock_move.py:919 #, python-format diff --git a/addons/stock/models/stock_production_lot.py b/addons/stock/models/stock_production_lot.py index 60f370fff51..a568cd80fe3 100644 --- a/addons/stock/models/stock_production_lot.py +++ b/addons/stock/models/stock_production_lot.py @@ -2,6 +2,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import api, fields, models, _ +from odoo.exceptions import UserError class ProductionLot(models.Model): @@ -27,6 +28,15 @@ class ProductionLot(models.Model): ('name_ref_uniq', 'unique (name, product_id)', 'The combination of serial number and product must be unique !'), ] + @api.model + def create(self, vals): + pack_id = self.env.context.get('active_pack_operation', False) + if pack_id: + pack = self.env['stock.pack.operation'].browse(pack_id) + if pack.picking_id and not pack.picking_id.picking_type_id.use_create_lots: + raise UserError(_("You are not allowed to create a lot for this picking type")) + return super(ProductionLot, self).create(vals) + @api.one @api.depends('quant_ids.qty') def _product_qty(self): diff --git a/addons/stock/views/stock_pack_operation_views.xml b/addons/stock/views/stock_pack_operation_views.xml index 5b6919dab83..cd8469d4672 100644 --- a/addons/stock/views/stock_pack_operation_views.xml +++ b/addons/stock/views/stock_pack_operation_views.xml @@ -85,7 +85,7 @@ + context="{'default_product_id': parent.product_id, 'active_pack_operation': parent.id}"/>