From 08416b2335f2657c0202d8879c2cf437b02b072f Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Mon, 23 May 2016 14:29:46 +0200 Subject: [PATCH 01/31] [FIX] account: partner_id set on a bank fee Used case: -Create several customer invoices and validate them -Register a payment without any partner_id and in a bank statement for an amount a bit lower than the total of the invoice (the difference is the paypal fees) -Reconcile the invoices with the payment and create a write-off for the paypal fees -When you close the bank statement, check the journal items, the paypal fees are automatically assigned with a partner. Fix: -When creating the account move line for the fee, if all the account move lines linked to the move are for different partners then you cannot determine the partner of the fee. opw:674822 --- addons/account/account_move_line.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index e7509edecdc..fe893b9ccbe 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -275,8 +275,9 @@ class account_move_line(osv.osv): #we propose to continue the same move by copying the ref, the name, the partner... move = move_obj.browse(cr, uid, move_id, context=context) data.setdefault('name', move.line_id[-1].name) + same_partner = len({l.partner_id for l in move.line_id}) == 1 for l in move.line_id: - data['partner_id'] = data.get('partner_id') or l.partner_id.id + data['partner_id'] = data.get('partner_id') or (same_partner and l.partner_id.id) data['ref'] = data.get('ref') or l.ref total += (l.debit or 0.0) - (l.credit or 0.0) From be48a1402cfcab733ce37910bc1b567b01f72747 Mon Sep 17 00:00:00 2001 From: Joren Van Onder Date: Wed, 25 May 2016 08:53:48 +0200 Subject: [PATCH 02/31] [FIX] hr_payroll: avoid infinite recursion The get_recursive_parent function seemingly depended on the ordering of the rule_categories recordset which happens to work fine in most cases because all data first defines the parent before defining the children rule categories. But if you happen to do it the other way around it won't work and it will infinitely call itself because: if rule_categories[0].parent_id: rule_categories = rule_categories[0].parent_id | rule_categories won't change the value of rule_categories[0]. opw-673222 (loosely related) --- .../hr_payroll/report/report_payslip_details.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/addons/hr_payroll/report/report_payslip_details.py b/addons/hr_payroll/report/report_payslip_details.py index f521cdb320d..7bfa1802ee4 100644 --- a/addons/hr_payroll/report/report_payslip_details.py +++ b/addons/hr_payroll/report/report_payslip_details.py @@ -37,13 +37,16 @@ class payslip_details_report(report_sxw.rml_parse): payslip_line = self.pool.get('hr.payslip.line') rule_cate_obj = self.pool.get('hr.salary.rule.category') - def get_recursive_parent(rule_categories): - if not rule_categories: - return [] - if rule_categories[0].parent_id: - rule_categories = rule_categories[0].parent_id | rule_categories - get_recursive_parent(rule_categories) - return rule_categories + def get_recursive_parent(current_rule_category, rule_categories = None): + if rule_categories: + rule_categories = current_rule_category | rule_categories + else: + rule_categories = current_rule_category + + if current_rule_category.parent_id: + return get_recursive_parent(current_rule_category.parent_id, rule_categories) + else: + return rule_categories res = [] result = {} From 5b299a20941e008b610511f9b327a6da201f7ed2 Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Tue, 24 May 2016 14:36:59 +0200 Subject: [PATCH 03/31] [FIX] calendar: editing an existing recurrent event It is not possible to edit the start_date, end_date, start_datetime, end_datetime and duration for a recurrent event due to the raesons explained in https://github.com/odoo/odoo/issues/10278 or see opw:665700 opw:677139 --- addons/calendar/calendar_view.xml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/addons/calendar/calendar_view.xml b/addons/calendar/calendar_view.xml index 50015b7a0ee..81ae9a3cc66 100644 --- a/addons/calendar/calendar_view.xml +++ b/addons/calendar/calendar_view.xml @@ -101,18 +101,19 @@ + - - + + - + From 31f50efe0a10cb5aff27e38255eee967bdf0b829 Mon Sep 17 00:00:00 2001 From: Richard deMeester Date: Wed, 25 May 2016 15:46:23 +1000 Subject: [PATCH 04/31] [FIX] stock_account: average cost with foreign currency Quants are created, and stock moves are updated, with the purchase value converted at current rates. However, the product average was calculated before that value was retrieved. This ensures the correct value is retrieved for the average cost calculation and will match the actual quants. Fixes #12163 Closes #12164 opw-678511 --- addons/stock_account/stock_account.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/addons/stock_account/stock_account.py b/addons/stock_account/stock_account.py index 203d896aee9..aae0f832db8 100644 --- a/addons/stock_account/stock_account.py +++ b/addons/stock_account/stock_account.py @@ -420,12 +420,14 @@ class stock_move(osv.osv): else: tmpl_dict[product_id] = 0 product_avail = qty_available + # if the incoming move is for a purchase order with foreign currency, need to call this to get the same value that the quant will use. + price_unit = self.pool.get('stock.move').get_price_unit(cr, uid, move, context=context) if product_avail <= 0: - new_std_price = move.price_unit + new_std_price = price_unit else: # Get the standard price amount_unit = product.standard_price - new_std_price = ((amount_unit * product_avail) + (move.price_unit * move.product_qty)) / (product_avail + move.product_qty) + new_std_price = ((amount_unit * product_avail) + (price_unit * move.product_qty)) / (product_avail + move.product_qty) tmpl_dict[product_id] += move.product_qty # Write the standard price, as SUPERUSER_ID because a warehouse manager may not have the right to write on products ctx = dict(context or {}, force_company=move.company_id.id) From 9516bad3cb9ec82fed666c818a37614478df982c Mon Sep 17 00:00:00 2001 From: qdp-odoo Date: Wed, 25 May 2016 10:55:39 +0200 Subject: [PATCH 05/31] [FIX] account: don't write the foreign currency on writeoff when several secondary currencies are involved --- addons/account/models/account_move.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 5cc899b9fad..285e8e6e843 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -830,7 +830,14 @@ class AccountMoveLine(models.Model): #if writeoff_acc_id specified, then create write-off move with value the remaining amount from move in self if writeoff_acc_id and writeoff_journal_id and remaining_moves: - writeoff_to_reconcile = remaining_moves._create_writeoff({'account_id': writeoff_acc_id.id, 'journal_id': writeoff_journal_id.id}) + all_aml_share_same_currency = all([x.currency_id == self[0].currency_id for x in self]) + writeoff_vals = { + 'account_id': writeoff_acc_id.id, + 'journal_id': writeoff_journal_id.id + } + if not all_aml_share_same_currency: + writeoff_vals['amount_currency'] = False + writeoff_to_reconcile = remaining_moves._create_writeoff(writeoff_vals) #add writeoff line to reconcile algo and finish the reconciliation remaining_moves = (remaining_moves + writeoff_to_reconcile).auto_reconcile_lines() From 1c58c67df2c4f96a8da1b8bbce0f1dece5861bea Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Wed, 25 May 2016 11:30:48 +0200 Subject: [PATCH 06/31] [FIX] web_settings_dashboard: access error When a user has the access rights "Configuration" or "Access Rights" regarding the "Administration" module category, the click on the "Settings" menu leads to an access error. This is because the dashboard fetches data about the number of installed modules ("installed_apps"), which requires access to "ir.module.module". Since it is not easily possible to hide a parts of the dashboard (the static templates do not recognize the "groups" attribute), we simply hide the dashboard for these users. opw-678531 --- addons/web_settings_dashboard/views/dashboard_views.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web_settings_dashboard/views/dashboard_views.xml b/addons/web_settings_dashboard/views/dashboard_views.xml index 3bf85772f4b..2a051860708 100644 --- a/addons/web_settings_dashboard/views/dashboard_views.xml +++ b/addons/web_settings_dashboard/views/dashboard_views.xml @@ -4,5 +4,5 @@ Dashboard web_settings_dashboard.main - + From a8248f2328a8cf946d96c2fe6083b5e20d40f74a Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Thu, 17 Mar 2016 14:12:46 +0100 Subject: [PATCH 07/31] [IMP] website_project_issue: my/issues/id form improvements 1/ Display a button for the project_user to come back in backend and edit the issue if they want --- addons/website_project_issue/views/project_issue_templates.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/website_project_issue/views/project_issue_templates.xml b/addons/website_project_issue/views/project_issue_templates.xml index 67729ac99e3..a19fa256366 100644 --- a/addons/website_project_issue/views/project_issue_templates.xml +++ b/addons/website_project_issue/views/project_issue_templates.xml @@ -53,6 +53,7 @@

Issue - + Edit Issue

From 0ac4a551324896367fab8b73e4cd2574018ca988 Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Thu, 17 Mar 2016 15:06:15 +0100 Subject: [PATCH 08/31] [IMP] website_mail: Display the message.atttachment_ids on message_thread --- addons/website_mail/views/website_mail.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/addons/website_mail/views/website_mail.xml b/addons/website_mail/views/website_mail.xml index d0df8e6b5a1..b65a19b3271 100644 --- a/addons/website_mail/views/website_mail.xml +++ b/addons/website_mail/views/website_mail.xml @@ -84,6 +84,14 @@
+
From 21e56e487ecb82cf0ee9e4c92652f2f873db0b3a Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Tue, 24 May 2016 16:35:34 +0200 Subject: [PATCH 09/31] [FIX] product_visible_discount: product without company_id When computing the real price of a product, a currency of reference is needed, first the currency of the product's company is privileged and if no company is set on the product then the currency of the user's company is taken. opw:678159 --- .../product_visible_discount/product_visible_discount.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/addons/product_visible_discount/product_visible_discount.py b/addons/product_visible_discount/product_visible_discount.py index 6cb9b5440bf..48605841fb0 100644 --- a/addons/product_visible_discount/product_visible_discount.py +++ b/addons/product_visible_discount/product_visible_discount.py @@ -33,14 +33,15 @@ class sale_order_line(osv.osv): currency_id = item.pricelist_id.currency_id product = product_obj.browse(cr, uid, product_id, context=context) + product_currency = (product.company_id and product.company_id.currency_id) or self.pool['res.users'].browse(cr, uid, uid).company_id.currency_id if not currency_id: - currency_id = product.company_id.currency_id + currency_id = product_currency cur_factor = 1.0 else: - if currency_id.id == product.company_id.currency_id.id: + if currency_id.id == product_currency.id: cur_factor = 1.0 else: - cur_factor = self.pool['res.currency']._get_conversion_rate(cr, uid, product.company_id.currency_id, currency_id, context=context) + cur_factor = self.pool['res.currency']._get_conversion_rate(cr, uid, product_currency, currency_id, context=context) product_uom = context and context.get('uom') or product.uom_id.id if uom and uom != product_uom: From 3ed55c540f4411cb1e953c59685eb5736d4c2309 Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Fri, 13 May 2016 12:15:32 +0200 Subject: [PATCH 10/31] [FIX] web: chardomain, don't allow to edit the input when not in edit mode. --- 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 ef57881d633..24a3895f206 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -794,7 +794,7 @@ '+ - karma + _t(' karma is required to perform this action. You can earn karma by having your answers upvoted by the community.') + ''); + karma + ' ' + _t(' karma is required to perform this action. You can earn karma by having your answers upvoted by the community.') + ''); var vote_alert = $(ev.currentTarget).parent().find("#vote_alert"); if (vote_alert.length == 0) { $(ev.currentTarget).parent().append($warning); From 97492a12a9f0975b80ebd43422aeebfb315dacb2 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Wed, 25 May 2016 12:34:20 +0200 Subject: [PATCH 12/31] [IMP] gamification: prevent misconfiguration Prevent selecting wrong field or models or computed fields Fixes #8545 --- addons/gamification/i18n/gamification.pot | 44 +++++++++++++++++++++-- addons/gamification/models/goal.py | 17 +++++++-- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/addons/gamification/i18n/gamification.pot b/addons/gamification/i18n/gamification.pot index 62def93f0e8..b722d230be8 100644 --- a/addons/gamification/i18n/gamification.pot +++ b/addons/gamification/i18n/gamification.pot @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 8.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-21 14:08+0000\n" -"PO-Revision-Date: 2015-01-21 14:08+0000\n" +"POT-Creation-Date: 2016-05-25 12:58+0000\n" +"PO-Revision-Date: 2016-05-25 12:58+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -562,6 +562,18 @@ msgstr "" msgid "Display Mode" msgstr "" +#. module: gamification +#: field:gamification.badge,display_name:0 +#: field:gamification.badge.user,display_name:0 +#: field:gamification.badge.user.wizard,display_name:0 +#: field:gamification.challenge,display_name:0 +#: field:gamification.challenge.line,display_name:0 +#: field:gamification.goal,display_name:0 +#: field:gamification.goal.definition,display_name:0 +#: field:gamification.goal.wizard,display_name:0 +msgid "Display Name" +msgstr "" + #. module: gamification #: field:gamification.goal.definition,display_mode:0 msgid "Displayed as" @@ -967,6 +979,18 @@ msgstr "" msgid "Last Message Date" msgstr "" +#. module: gamification +#: field:gamification.badge,__last_update:0 +#: field:gamification.badge.user,__last_update:0 +#: field:gamification.badge.user.wizard,__last_update:0 +#: field:gamification.challenge,__last_update:0 +#: field:gamification.challenge.line,__last_update:0 +#: field:gamification.goal,__last_update:0 +#: field:gamification.goal.definition,__last_update:0 +#: field:gamification.goal.wizard,__last_update:0 +msgid "Last Modified on" +msgstr "" + #. module: gamification #: field:gamification.challenge,last_report_date:0 msgid "Last Report Date" @@ -1585,6 +1609,22 @@ msgstr "" msgid "The maximum number of time this badge can be sent per month per person." msgstr "" +#. module: gamification +#: code:addons/gamification/models/goal.py:160 +#, python-format +msgid "The model configuration for the definition %s seems incorrect, please check it.\n" +"\n" +"%s not found" +msgstr "" + +#. module: gamification +#: code:addons/gamification/models/goal.py:158 +#, python-format +msgid "The model configuration for the definition %s seems incorrect, please check it.\n" +"\n" +"%s not stored" +msgstr "" + #. module: gamification #: help:gamification.goal.definition,model_id:0 msgid "The model object for the field to evaluate" diff --git a/addons/gamification/models/goal.py b/addons/gamification/models/goal.py index ad37762d10b..a63431a83c4 100644 --- a/addons/gamification/models/goal.py +++ b/addons/gamification/models/goal.py @@ -148,18 +148,31 @@ class gamification_goal_definition(osv.Model): raise osv.except_osv(_('Error!'),_("The domain for the definition %s seems incorrect, please check it.\n\n%s" % (definition.name, msg))) return True + def _check_model_validity(self, cr, uid, ids, context=None): + """ make sure the selected field and model are usable""" + for definition in self.browse(cr, uid, ids, context=context): + try: + model = self.pool[definition.model_id.model] + field = model._fields[definition.field_id.name] + if not field.store: + raise UserError(_("The model configuration for the definition %s seems incorrect, please check it.\n\n%s not stored") % (definition.name, definition.field_id.name)) + except KeyError, e: + raise UserError(_("The model configuration for the definition %s seems incorrect, please check it.\n\n%s not found") % (definition.name, e.message)) + def create(self, cr, uid, vals, context=None): res_id = super(gamification_goal_definition, self).create(cr, uid, vals, context=context) if vals.get('computation_mode') in ('count', 'sum'): self._check_domain_validity(cr, uid, [res_id], context=context) - + if vals.get('field_id'): + self._check_model_validity(cr, uid, [res_id], context=context) return res_id def write(self, cr, uid, ids, vals, context=None): res = super(gamification_goal_definition, self).write(cr, uid, ids, vals, context=context) if vals.get('computation_mode', 'count') in ('count', 'sum') and (vals.get('domain') or vals.get('model_id')): self._check_domain_validity(cr, uid, ids, context=context) - + if vals.get('field_id') or vals.get('model_id') or vals.get('batch_mode'): + self._check_model_validity(cr, uid, ids, context=context) return res def on_change_model_id(self, cr, uid, ids, model_id, context=None): From 8cdba8c5aae26beb3d2d14836114750510101ed6 Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Wed, 25 May 2016 13:42:33 +0200 Subject: [PATCH 13/31] =?UTF-8?q?[FIX]=C2=A0account:=20get=5Fformview=5Fid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For a type 'in_refund', the supplier account invoice form must be taken. opw:678498 --- addons/account/models/account_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index eb6aa6f45c9..8eb560a614a 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -522,7 +522,7 @@ class AccountInvoice(models.Model): @api.multi def get_formview_id(self): """ Update form view id of action to open the invoice """ - if self.type == 'in_invoice': + if self.type in ('in_invoice', 'in_refund'): return self.env.ref('account.invoice_supplier_form').id else: return self.env.ref('account.invoice_form').id From 526c38cdb145143407cc0e5504574e72f7e720a0 Mon Sep 17 00:00:00 2001 From: Joren Van Onder Date: Wed, 25 May 2016 15:03:29 +0200 Subject: [PATCH 14/31] [FIX] point_of_sale: set callbacks for weight and price barcodes c8732bea1e8471b90ac0c118b212a2d6ae84180a did not take into account that we don't have specific callbacks for weight or price type barcodes. Those where handled by the product callback. opw-678556 --- addons/point_of_sale/static/src/js/screens.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index 06977a3285c..f90d861b67a 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -131,6 +131,8 @@ var ScreenWidget = PosBaseWidget.extend({ this.pos.barcode_reader.set_action_callback({ 'cashier': _.bind(self.barcode_cashier_action, self), 'product': _.bind(self.barcode_product_action, self), + 'weight': _.bind(self.barcode_product_action, self), + 'price': _.bind(self.barcode_product_action, self), 'client' : _.bind(self.barcode_client_action, self), 'discount': _.bind(self.barcode_discount_action, self), 'error' : _.bind(self.barcode_error_action, self), From 4c7a9bdac4850674c47253bde432d020953e66de Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Wed, 25 May 2016 14:54:00 +0200 Subject: [PATCH 15/31] [FIX] web: raise a warning for bad domain When a user wrote a wrong value in char_domain field it should raise a warning message instead of a traceback. Backport of b3a88b6ed846a13c0cd07cc25ea49bccbdf84aa8 opw:676783 --- addons/web/i18n/web.pot | 14 ++++++++++++++ addons/web/static/src/js/view_form.js | 8 +++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/addons/web/i18n/web.pot b/addons/web/i18n/web.pot index 6522ed569ce..3217d20f3fe 100644 --- a/addons/web/i18n/web.pot +++ b/addons/web/i18n/web.pot @@ -1073,6 +1073,13 @@ msgstr "" msgid "Error" msgstr "" +#. module: web +#. openerp-web +#: code:addons/web/static/src/js/views/form_widgets.js:2600 +#, python-format +msgid "Error: Bad domain" +msgstr "" + #. module: web #: code:addons/web/controllers/main.py:764 #: code:addons/web/controllers/main.py:805 @@ -2318,6 +2325,13 @@ msgstr "" msgid "The database has been duplicated." msgstr "" +#. module: web +#. openerp-web +#: code:addons/web/static/src/js/views/form_widgets.js:2600 +#, python-format +msgid "The domain is wrong." +msgstr "" + #. module: web #. openerp-web #: code:addons/web/static/src/js/view_form.js:5637 diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index cdf73ee06ae..6588340e4d7 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -2593,7 +2593,13 @@ instance.web.form.FieldCharDomain = instance.web.form.AbstractField.extend(insta this.$el.html(instance.web.qweb.render("FieldCharDomain", {widget: this})); if (this.get('value')) { var model = this.options.model || this.field_manager.get_field_value(this.options.model_field); - var domain = instance.web.pyeval.eval('domain', this.get('value')); + try{ + var domain = pyeval.eval('domain', this.get('value')); + } + catch(e){ + this.do_warn(_t('Error: Bad domain'), _t('The domain is wrong.')); + return; + } var ds = new instance.web.DataSetStatic(self, model, self.build_context()); ds.call('search_count', [domain, self.build_context()]).then(function (results) { $('.oe_domain_count', self.$el).text(results + _t(' records selected')); From 4176030cd3f0ab8895beb7a6634d57a145e44167 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Wed, 25 May 2016 18:07:05 +0200 Subject: [PATCH 16/31] [FIX] calandar: all day events email notification When sending a notification email to an event attendee for an all day event, the timezone must be ignored as the `start` and `stop` datetime are stored as the day date + '00:00:00'. If the timezone is applied, for users being in a negative timezone (such as an American timezone), the day displayed would be the day just before. opw-677019 --- addons/calendar/calendar_data.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/addons/calendar/calendar_data.xml b/addons/calendar/calendar_data.xml index 787933610ad..710524b678e 100644 --- a/addons/calendar/calendar_data.xml +++ b/addons/calendar/calendar_data.xml @@ -107,11 +107,11 @@
-
${object.event_id.get_interval(object.event_id.start, 'dayname', tz=object.partner_id.tz)}
+
${object.event_id.get_interval(object.event_id.start, 'dayname', tz=object.partner_id.tz if not object.event_id.allday else None)}
- ${object.event_id.get_interval(object.event_id.start,'day', tz=object.partner_id.tz)} + ${object.event_id.get_interval(object.event_id.start,'day', tz=object.partner_id.tz if not object.event_id.allday else None)}
-
${object.event_id.get_interval(object.event_id.start, 'month', tz=object.partner_id.tz)}
+
${object.event_id.get_interval(object.event_id.start, 'month', tz=object.partner_id.tz if not object.event_id.allday else None)}
${not object.event_id.allday and object.event_id.get_interval(object.event_id.start, 'time', tz=object.partner_id.tz) or ''}
@@ -240,11 +240,11 @@
-
${object.event_id.get_interval(object.event_id.start, 'dayname', tz=object.partner_id.tz)}
+
${object.event_id.get_interval(object.event_id.start, 'dayname', tz=object.partner_id.tz if not object.event_id.allday else None)}
- ${object.event_id.get_interval(object.event_id.start,'day', tz=object.partner_id.tz)} + ${object.event_id.get_interval(object.event_id.start,'day', tz=object.partner_id.tz if not object.event_id.allday else None)}
-
${object.event_id.get_interval(object.event_id.start, 'month', tz=object.partner_id.tz)}
+
${object.event_id.get_interval(object.event_id.start, 'month', tz=object.partner_id.tz if not object.event_id.allday else None)}
${not object.event_id.allday and object.event_id.get_interval(object.event_id.start, 'time', tz=object.partner_id.tz) or ''}
@@ -372,11 +372,11 @@
-
${object.event_id.get_interval(object.event_id.start, 'dayname', tz=object.partner_id.tz)}
+
${object.event_id.get_interval(object.event_id.start, 'dayname', tz=object.partner_id.tz if not object.event_id.allday else None)}
- ${object.event_id.get_interval(object.event_id.start,'day', tz=object.partner_id.tz)} + ${object.event_id.get_interval(object.event_id.start,'day', tz=object.partner_id.tz if not object.event_id.allday else None)}
-
${object.event_id.get_interval(object.event_id.start, 'month', tz=object.partner_id.tz)}
+
${object.event_id.get_interval(object.event_id.start, 'month', tz=object.partner_id.tz if not object.event_id.allday else None)}
${not object.event_id.allday and object.event_id.get_interval(object.event_id.start, 'time', tz=object.partner_id.tz) or ''}
From 22f4aa1c4341cd2e8008b730f676473f025cbb42 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Wed, 25 May 2016 18:16:40 +0200 Subject: [PATCH 17/31] [FIX] crm: merge leads in multi-company When merging leads with a company set different than the current user company, it failed because the notification email (the message written in the thread summarizing the merge) couldn't read the company name (the `name_get` call on the company) because of the multi-company record rule. `name_get` can be safely called as `sudo`, as it does nothing else than returning the name of the record. This is already done for the many2one links in the web client anyway (You can see leads from a company different than yours, you can see the company name to which the leads belongs to, but you can't click on the company many2one link) opw-677986 --- addons/crm/crm_lead.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index 711292eb4e3..f33d4c16ad5 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -528,11 +528,11 @@ class crm_lead(format_address, osv.osv): value = dict(key).get(lead[field_name], lead[field_name]) elif field.type == 'many2one': if lead[field_name]: - value = lead[field_name].name_get()[0][1] + value = lead[field_name].sudo().name_get()[0][1] elif field.type == 'many2many': if lead[field_name]: for val in lead[field_name]: - field_value = val.name_get()[0][1] + field_value = val.sudo().name_get()[0][1] value += field_value + "," else: value = lead[field_name] From 9772bbef07e2f13a85faf7f6dc737d7c8be8119c Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Wed, 25 May 2016 23:38:28 +0200 Subject: [PATCH 18/31] [FIX] web: fix backport #4c7a9bd --- addons/web/static/src/js/view_form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 6588340e4d7..27e201b2e3b 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -2594,7 +2594,7 @@ instance.web.form.FieldCharDomain = instance.web.form.AbstractField.extend(insta if (this.get('value')) { var model = this.options.model || this.field_manager.get_field_value(this.options.model_field); try{ - var domain = pyeval.eval('domain', this.get('value')); + var domain = instance.web.pyeval.eval('domain', this.get('value')); } catch(e){ this.do_warn(_t('Error: Bad domain'), _t('The domain is wrong.')); From 44e8b92beb4d066c6192fd723cff8299f19d9628 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 25 May 2016 15:10:45 +0200 Subject: [PATCH 19/31] [FIX] translate: don't translate DOCTYPE tag --- openerp/tools/translate.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openerp/tools/translate.py b/openerp/tools/translate.py index 756edfb61ce..a852f05de77 100644 --- a/openerp/tools/translate.py +++ b/openerp/tools/translate.py @@ -32,7 +32,7 @@ _logger = logging.getLogger(__name__) # used to notify web client that these translations should be loaded in the UI WEB_TRANSLATION_COMMENT = "openerp-web" -SKIPPED_ELEMENTS = ('script', 'style') +SKIPPED_ELEMENTS = ('script', 'style', 'title') _LOCALE2WIN32 = { 'af_ZA': 'Afrikaans_South Africa', @@ -231,7 +231,8 @@ class XMLTranslator(object): isinstance(node, SKIPPED_ELEMENT_TYPES) or node.tag in SKIPPED_ELEMENTS or node.get("t-translation", "").strip() == "off" or - node.tag == "attribute" and node.get("name") not in TRANSLATED_ATTRS + node.tag == "attribute" and node.get("name") not in TRANSLATED_ATTRS or + not node.getparent() and node.text and ' Date: Wed, 25 May 2016 13:58:09 +0200 Subject: [PATCH 20/31] [FIX] im_livechat: don't translate livechat javascript template --- addons/im_livechat/views/im_livechat_channel_templates.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/im_livechat/views/im_livechat_channel_templates.xml b/addons/im_livechat/views/im_livechat_channel_templates.xml index 0efd2310a14..dbfb91a05eb 100644 --- a/addons/im_livechat/views/im_livechat_channel_templates.xml +++ b/addons/im_livechat/views/im_livechat_channel_templates.xml @@ -138,11 +138,11 @@ From fe348e280d81120285196e4bf8864255a765f3cb Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 3 May 2016 11:54:17 +0200 Subject: [PATCH 21/31] [FIX] report: some Wkhtmltopdf installation can return an empty version --- addons/report/models/report.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/report/models/report.py b/addons/report/models/report.py index ed93ed9344d..af1ebec359e 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -50,7 +50,7 @@ except (OSError, IOError): else: _logger.info('Will use the Wkhtmltopdf binary at %s' % _get_wkhtmltopdf_bin()) out, err = process.communicate() - version = re.search('([0-9.]+)', out).group(0) + version = re.search('([0-9.]+)', out or "0").group(0) if LooseVersion(version) < LooseVersion('0.12.0'): _logger.info('Upgrade Wkhtmltopdf to (at least) 0.12.0') wkhtmltopdf_state = 'upgrade' From a4687c6e42a7b0ec6b8d98dc2af7fe2d1c3272d0 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Thu, 26 May 2016 08:29:39 +0200 Subject: [PATCH 22/31] [FIX] gamification: bad backport to 8.0 UserError was defined in version 9, not 8 --- addons/gamification/models/goal.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/addons/gamification/models/goal.py b/addons/gamification/models/goal.py index a63431a83c4..969d4321bab 100644 --- a/addons/gamification/models/goal.py +++ b/addons/gamification/models/goal.py @@ -155,9 +155,11 @@ class gamification_goal_definition(osv.Model): model = self.pool[definition.model_id.model] field = model._fields[definition.field_id.name] if not field.store: - raise UserError(_("The model configuration for the definition %s seems incorrect, please check it.\n\n%s not stored") % (definition.name, definition.field_id.name)) + raise osv.except_osv(_('Error!'), + _("The model configuration for the definition %s seems incorrect, please check it.\n\n%s not stored") % (definition.name, definition.field_id.name)) except KeyError, e: - raise UserError(_("The model configuration for the definition %s seems incorrect, please check it.\n\n%s not found") % (definition.name, e.message)) + raise osv.except_osv(_('Error!'), + _("The model configuration for the definition %s seems incorrect, please check it.\n\n%s not found") % (definition.name, e.message)) def create(self, cr, uid, vals, context=None): res_id = super(gamification_goal_definition, self).create(cr, uid, vals, context=context) From 37bbe87d5792c879130e5f1e491f743cbc50dc1e Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Thu, 26 May 2016 08:33:20 +0200 Subject: [PATCH 23/31] [INP] gamification: skip check for not required fields Could get a definition with a model only --- addons/gamification/models/goal.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/gamification/models/goal.py b/addons/gamification/models/goal.py index 969d4321bab..42fd073b58e 100644 --- a/addons/gamification/models/goal.py +++ b/addons/gamification/models/goal.py @@ -152,6 +152,9 @@ class gamification_goal_definition(osv.Model): """ make sure the selected field and model are usable""" for definition in self.browse(cr, uid, ids, context=context): try: + if not definition.model_id or not definition.field_id: + continue + model = self.pool[definition.model_id.model] field = model._fields[definition.field_id.name] if not field.store: From 6c129e99546497b33a3150d6e01647c1dccb4585 Mon Sep 17 00:00:00 2001 From: rocksolidsolutions Date: Wed, 25 May 2016 08:57:33 -0700 Subject: [PATCH 24/31] [CLA] Rock Solid Solutions signs corporate CLA. Closes #12182 --- doc/cla/corporate/rocksolidsolutions.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 doc/cla/corporate/rocksolidsolutions.md diff --git a/doc/cla/corporate/rocksolidsolutions.md b/doc/cla/corporate/rocksolidsolutions.md new file mode 100644 index 00000000000..133c19de35c --- /dev/null +++ b/doc/cla/corporate/rocksolidsolutions.md @@ -0,0 +1,15 @@ +United States, 2016-05-25 + +Rock Solid Solutions, LLC agrees to the terms of the Odoo Corporate Contributor License +Agreement v1.0. + +I declare that I am authorized and able to make this agreement and sign this +declaration. + +Signed, + +Daniel Kauffman, Manager rocksolidsolutions@users.noreply.github.com + +List of contributors: + +Daniel Kauffman rocksolidsolutions@users.noreply.github.com From 9c28b6fbfa9344f6cd4a1765ef5d2979cc967957 Mon Sep 17 00:00:00 2001 From: 65HQqp5QTq8QwA3f <65HQqp5QTq8QwA3f@users.noreply.github.com> Date: Tue, 10 Nov 2015 10:55:42 -0800 Subject: [PATCH 25/31] [FIX] sale: propagate context Closes #9521 --- addons/sale/sale.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 67f04c45fc3..29a572c8e0f 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -539,7 +539,7 @@ class sale_order(osv.osv): continue elif (line.state in states): lines.append(line.id) - created_lines = obj_sale_order_line.invoice_line_create(cr, uid, lines) + created_lines = obj_sale_order_line.invoice_line_create(cr, uid, lines, context=context) if created_lines: invoices.setdefault(o.partner_invoice_id.id or o.partner_id.id, []).append((o, created_lines)) if not invoices: From e07fa2601e977a5d1d77accc7704bc33c7bd885c Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Thu, 26 May 2016 10:24:19 +0200 Subject: [PATCH 26/31] [FIX] doc: update css file to reflect 8ce16c3 --- doc/_extensions/odoo/static/style.css | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/_extensions/odoo/static/style.css b/doc/_extensions/odoo/static/style.css index 65ad613a94e..1d48dea23b0 100644 --- a/doc/_extensions/odoo/static/style.css +++ b/doc/_extensions/odoo/static/style.css @@ -9473,18 +9473,18 @@ h6, line-height: 1.4; } @media (min-width: 1200px) { - .has_code_col h1, - .has_code_col h2, - .has_code_col h3, - .has_code_col h4, - .has_code_col h5, - .has_code_col h6, - .has_code_col .h1, - .has_code_col .h2, - .has_code_col .h3, - .has_code_col .h4, - .has_code_col .h5, - .has_code_col .h6 { + .has_code_col .doc-aside h1, + .has_code_col .doc-aside h2, + .has_code_col .doc-aside h3, + .has_code_col .doc-aside h4, + .has_code_col .doc-aside h5, + .has_code_col .doc-aside h6, + .has_code_col .doc-aside .h1, + .has_code_col .doc-aside .h2, + .has_code_col .doc-aside .h3, + .has_code_col .doc-aside .h4, + .has_code_col .doc-aside .h5, + .has_code_col .doc-aside .h6 { color: white; } } @@ -11928,7 +11928,7 @@ main.index.animating .card { font-size: 65%; } @media (min-width: 1200px) { - .has_code_col .card.top .container h1 { + .has_code_col .doc-aside .card.top .container h1 { color: white; } } @@ -11969,7 +11969,7 @@ main.index.animating .card { } } @media screen and (min-width: 768px) and (min-width: 1200px) { - .has_code_col .card.top .container h1 { + .has_code_col .doc-aside .card.top .container h1 { color: white; } } @@ -12010,7 +12010,7 @@ main.index.animating .card { font-size: 65%; } @media (min-width: 1200px) { - .has_code_col .toctree-wrapper > ul > li.toctree-l1 > span { + .has_code_col .doc-aside .toctree-wrapper > ul > li.toctree-l1 > span { color: white; } } From dbdc8e1ceffc11d80dc336ef471eecffdadd5b02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Kuzn=C3=ADk?= Date: Mon, 18 Aug 2014 13:35:58 +0100 Subject: [PATCH 27/31] [FIX] server: Do not listen when --no-xmlrpc is set This is a fix for f04f409943b8bd8f4bd2653e368523d1cc0d8246, which only prevented the workers from being spawned in Prefork mode, while the socket was still being bound to - this is a problem when starting a worker-only server as it cannot coexist with the XMLRPC server on the same machine. Closes #1828 --- openerp/service/server.py | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/openerp/service/server.py b/openerp/service/server.py index 46c5c15fe1a..f2d67c000ef 100644 --- a/openerp/service/server.py +++ b/openerp/service/server.py @@ -428,7 +428,8 @@ class PreforkServer(CommonServer): """ def __init__(self, app): # config - self.address = (config['xmlrpc_interface'] or '0.0.0.0', config['xmlrpc_port']) + self.address = config['xmlrpc'] and \ + (config['xmlrpc_interface'] or '0.0.0.0', config['xmlrpc_port']) self.population = config['workers'] self.timeout = config['limit_time_real'] self.limit_request = config['limit_request'] @@ -603,12 +604,13 @@ class PreforkServer(CommonServer): signal.signal(signal.SIGQUIT, dumpstacks) signal.signal(signal.SIGUSR1, log_ormcache_stats) - # listen to socket - self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - self.socket.setblocking(0) - self.socket.bind(self.address) - self.socket.listen(8 * self.population) + if self.address: + # listen to socket + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.socket.setblocking(0) + self.socket.bind(self.address) + self.socket.listen(8 * self.population) def stop(self, graceful=True): if self.long_polling_pid is not None: @@ -632,7 +634,8 @@ class PreforkServer(CommonServer): _logger.info("Stopping forcefully") for pid in self.workers.keys(): self.worker_kill(pid, signal.SIGTERM) - self.socket.close() + if self.socket: + self.socket.close() def run(self, preload, stop): self.start() @@ -735,11 +738,13 @@ class Worker(object): _logger.info("Worker %s (%s) alive", self.__class__.__name__, self.pid) # Reseed the random number generator random.seed() - # Prevent fd inherientence close_on_exec - flags = fcntl.fcntl(self.multi.socket, fcntl.F_GETFD) | fcntl.FD_CLOEXEC - fcntl.fcntl(self.multi.socket, fcntl.F_SETFD, flags) - # reset blocking status - self.multi.socket.setblocking(0) + if self.multi.socket: + # Prevent fd inheritance: close_on_exec + flags = fcntl.fcntl(self.multi.socket, fcntl.F_GETFD) | fcntl.FD_CLOEXEC + fcntl.fcntl(self.multi.socket, fcntl.F_SETFD, flags) + # reset blocking status + self.multi.socket.setblocking(0) + signal.signal(signal.SIGINT, self.signal_handler) signal.signal(signal.SIGTERM, signal.SIG_DFL) signal.signal(signal.SIGCHLD, signal.SIG_DFL) @@ -857,7 +862,8 @@ class WorkerCron(Worker): def start(self): os.nice(10) # mommy always told me to be nice with others... Worker.start(self) - self.multi.socket.close() + if self.multi.socket: + self.multi.socket.close() #---------------------------------------------------------- # start/stop public api From 4ffd2fdd81aad675194f9c21c097abdc99a0d3c0 Mon Sep 17 00:00:00 2001 From: Damien Bouvy Date: Thu, 26 May 2016 10:27:44 +0200 Subject: [PATCH 28/31] [FIX] sale: multi-company tax filtering When the admin creates a SO, he has access to all taxes (since ir.rules do not apply to him); therefore in some cases, the SO could be created with SO lines that have taxes from other companies. This usually does not make sense. From this revision on, only taxes that are in the same company as the SO are applied to the lines. If no company is set, then no filtering is done. --- addons/sale/sale.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 4176d75229a..ad6ef43a036 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -545,17 +545,9 @@ class SaleOrderLine(models.Model): def _compute_tax_id(self): for line in self: fpos = line.order_id.fiscal_position_id or line.order_id.partner_id.property_account_position_id - if fpos: - # The superuser is used by website_sale in order to create a sale order. We need to make - # sure we only select the taxes related to the company of the partner. This should only - # apply if the partner is linked to a company. - if self.env.uid == SUPERUSER_ID and line.order_id.company_id: - taxes = fpos.map_tax(line.product_id.taxes_id).filtered(lambda r: r.company_id == line.order_id.company_id) - else: - taxes = fpos.map_tax(line.product_id.taxes_id) - line.tax_id = taxes - else: - line.tax_id = line.product_id.taxes_id if line.product_id.taxes_id else False + # If company_id is set, always filter taxes by the company + taxes = line.product_id.taxes_id.filtered(lambda r: not line.company_id or r.company_id == line.company_id) + line.tax_id = fpos.map_tax(taxes) if fpos else taxes @api.multi def _prepare_order_line_procurement(self, group_id=False): From 66221968b8024f589d361ead74312a24ae02cd99 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Thu, 26 May 2016 11:44:00 +0200 Subject: [PATCH 29/31] [FIX] crm_partner_assign: minimum access rights to employee Give the same as access rights to the employee as for the public user. This patch is needed to allow a user to access the partner form. Same for portal. The list of grades in not a confidential information. Fixes #7719 --- addons/crm_partner_assign/security/ir.model.access.csv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/crm_partner_assign/security/ir.model.access.csv b/addons/crm_partner_assign/security/ir.model.access.csv index 61b35dde142..9aebe66635a 100644 --- a/addons/crm_partner_assign/security/ir.model.access.csv +++ b/addons/crm_partner_assign/security/ir.model.access.csv @@ -3,6 +3,8 @@ access_ crm_lead_report_assign,crm.lead.report.assign,model_crm_lead_report_assi access_ crm_lead_report_assign_all,crm.lead.report.assign.all,model_crm_lead_report_assign,base.group_user,1,0,0,0 access_crm_partner_report,crm.partner.report.assign.all,model_crm_partner_report_assign,base.group_sale_salesman,1,0,0,0 access_res_partner_grade,res.partner.grade,model_res_partner_grade,base.group_sale_salesman,1,1,1,0 +access_res_partner_grade_employee,res.partner.grade,model_res_partner_grade,base.group_user,1,0,0,0 +access_res_partner_grade_portal,res.partner.grade,model_res_partner_grade,base.group_portal,1,0,0,0 access_res_partner_grade_public,res.partner.grade,model_res_partner_grade,base.group_public,1,0,0,0 access_res_partner_grade_manager,res.partner.grade.manager,model_res_partner_grade,base.group_sale_manager,1,1,1,1 access_res_partner_activation_user,res.partner.activation.user,model_res_partner_activation,base.group_user,1,0,0,0 From 6c6a9f3d609765111e50af0656f637b30724de84 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Thu, 26 May 2016 13:05:46 +0200 Subject: [PATCH 30/31] [FIX] *: replace uses of `except_osv` with `UserError` that have been forgotten during previous forward-ports --- addons/crm/base_partner_merge.py | 2 +- addons/point_of_sale/point_of_sale.py | 2 +- addons/purchase/purchase.py | 5 ++--- addons/sale_stock/sale_stock.py | 2 +- addons/stock/wizard/stock_return_picking.py | 2 +- addons/stock_account/product.py | 2 +- addons/stock_account/stock_account.py | 2 +- openerp/addons/base/res/res_users.py | 2 +- 8 files changed, 9 insertions(+), 10 deletions(-) diff --git a/addons/crm/base_partner_merge.py b/addons/crm/base_partner_merge.py index 8baf69a5a7a..95ad18f044f 100644 --- a/addons/crm/base_partner_merge.py +++ b/addons/crm/base_partner_merge.py @@ -306,7 +306,7 @@ class MergePartnerAutomatic(osv.TransientModel): for partner_id in partner_ids: child_ids = child_ids.union(set(proxy.search(cr, uid, [('id', 'child_of', [partner_id])])) - set([partner_id])) if set(partner_ids).intersection(child_ids): - raise osv.except_osv(_('Error'), _("You cannot merge a contact with one of his parent.")) + raise UserError(_("You cannot merge a contact with one of his parent.")) if openerp.SUPERUSER_ID != uid and len(set(partner.email for partner in proxy.browse(cr, uid, partner_ids, context=context))) > 1: raise UserError(_("All contacts must have the same email. Only the Administrator can merge contacts with different emails.")) diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index ead3b4ac119..9ddbc244051 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -1546,7 +1546,7 @@ class product_template(osv.osv): product_ctx = dict(context or {}, active_test=False) if self.search_count(cr, uid, [('id', 'in', ids), ('available_in_pos', '=', True)], context=product_ctx): if self.pool['pos.session'].search_count(cr, uid, [('state', '!=', 'closed')], context=context): - raise osv.except_osv(_('Error!'), + raise UserError( _('You cannot delete a product saleable in point of sale while a session is still opened.')) return super(product_template, self).unlink(cr, uid, ids, context=context) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 446da4cf081..15226a4022b 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -435,7 +435,7 @@ class purchase_order(osv.osv): company_id = context.get('company_id') or self.pool.get('res.users')._get_company(cr, uid, context=context) if not company_id: - raise osv.except_osv(_('Error!'), _('There is no default company for the current user!')) + raise UserError(_('There is no default company for the current user!')) fp = self.pool['account.fiscal.position'].get_fiscal_position(cr, uid, company_id, partner_id, context=context) supplier_address = partner.address_get(cr, uid, [partner_id], ['default'], context=context) supplier = partner.browse(cr, uid, partner_id, context=context) @@ -578,8 +578,7 @@ class purchase_order(osv.osv): if not any(line.state != 'cancel' for line in po.order_line): raise UserError(_('You cannot confirm a purchase order without any purchase order line.')) if po.invoice_method == 'picking' and not any([l.product_id and l.product_id.type in ('product', 'consu') and l.state != 'cancel' for l in po.order_line]): - raise osv.except_osv( - _('Error!'), + raise UserError( _("You cannot confirm a purchase order with Invoice Control Method 'Based on incoming shipments' that doesn't contain any stockable item.")) for line in po.order_line: if line.state=='draft': diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index 65f37e985e3..f3fc9b6d3ee 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -375,7 +375,7 @@ class sale_order_line(osv.osv): for procurement in lines.mapped('procurement_ids'): for move in procurement.move_ids: if move.state == 'done' and not move.scrapped: - raise osv.except_osv(_('Invalid Action!'), _('You cannot cancel a sale order line which is linked to a stock move already done.')) + raise UserError(_('You cannot cancel a sale order line which is linked to a stock move already done.')) return super(sale_order_line, self).button_cancel(cr, uid, ids, context=context) class stock_move(osv.osv): diff --git a/addons/stock/wizard/stock_return_picking.py b/addons/stock/wizard/stock_return_picking.py index ce46f07f764..39e588bfd7c 100644 --- a/addons/stock/wizard/stock_return_picking.py +++ b/addons/stock/wizard/stock_return_picking.py @@ -60,7 +60,7 @@ class stock_return_picking(osv.osv_memory): context = {} if context and context.get('active_ids', False): if len(context.get('active_ids')) > 1: - raise osv.except_osv(_('Warning!'), _("You may only return one picking at a time!")) + raise UserError(_("You may only return one picking at a time!")) res = super(stock_return_picking, self).default_get(cr, uid, fields, context=context) record_id = context and context.get('active_id', False) or False uom_obj = self.pool.get('product.uom') diff --git a/addons/stock_account/product.py b/addons/stock_account/product.py index 728ea544a07..fd433279348 100644 --- a/addons/stock_account/product.py +++ b/addons/stock_account/product.py @@ -134,7 +134,7 @@ class product_template(osv.osv): if not counterpart_account: counterpart_account = product.categ_id.property_account_expense_categ and product.categ_id.property_account_expense_categ.id or False if not counterpart_account: - raise osv.except_osv(_('Error!'), _('No expense account defined on the product %s or on its category') % (product.name)) + raise UserError(_('No expense account defined on the product %s or on its category') % (product.name)) if diff * qty > 0: amount_diff = qty * diff debit_account_id = counterpart_account diff --git a/addons/stock_account/stock_account.py b/addons/stock_account/stock_account.py index bee410ae3ca..237da2f677a 100644 --- a/addons/stock_account/stock_account.py +++ b/addons/stock_account/stock_account.py @@ -196,7 +196,7 @@ class stock_quant(osv.osv): :param context: context dictionary that can explicitly mention the company to consider via the 'force_company' key :returns: journal_id, source account, destination account, valuation account - :raise: osv.except_osv() is any mandatory account or journal is not defined. + :raise: openerp.exceptions.UserError if any mandatory account or journal is not defined. """ product_obj = self.pool.get('product.template') accounts = product_obj.get_product_accounts(cr, uid, move.product_id.product_tmpl_id.id, context) diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index dda40e32d7f..38625280089 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -527,7 +527,7 @@ class res_users(osv.osv): :return: True :raise: openerp.exceptions.AccessDenied when old password is wrong - :raise: except_osv when new password is not set or empty + :raise: openerp.exceptions.UserError when new password is not set or empty """ self.check(cr.dbname, uid, old_passwd) if new_passwd: From f92939e75c2d24f26c7e6e68875d0d69d630f6c4 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Thu, 26 May 2016 13:34:11 +0200 Subject: [PATCH 31/31] [I18N] im_livechat: export source terms --- addons/im_livechat/i18n/im_livechat.pot | 119 ++++++------------------ 1 file changed, 30 insertions(+), 89 deletions(-) diff --git a/addons/im_livechat/i18n/im_livechat.pot b/addons/im_livechat/i18n/im_livechat.pot index 724c5cb037d..27b293522f4 100644 --- a/addons/im_livechat/i18n/im_livechat.pot +++ b/addons/im_livechat/i18n/im_livechat.pot @@ -4,10 +4,10 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 9.0\n" +"Project-Id-Version: Odoo Server 9.0c\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-10-09 09:20+0000\n" -"PO-Revision-Date: 2015-10-09 09:20+0000\n" +"POT-Creation-Date: 2016-05-26 11:19+0000\n" +"PO-Revision-Date: 2016-05-26 11:19+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -15,19 +15,6 @@ msgstr "" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" -#. module: im_livechat -#. openerp-web -#: code:addons/im_livechat/static/src/js/im_livechat.js:222 -#, python-format -msgid " for the following reason: %s" -msgstr "" - -#. module: im_livechat -#: model:ir.ui.view,arch_db:im_livechat.loader -msgid "\", {modules:modules, use_cors: false});\n" -" });" -msgstr "" - #. module: im_livechat #: model:ir.model.fields,field_description:im_livechat.field_im_livechat_report_operator_nbr_channel msgid "# of channel" @@ -44,20 +31,6 @@ msgstr "" msgid "% Happy" msgstr "" -#. module: im_livechat -#: model:ir.ui.view,arch_db:im_livechat.support_page -msgid "<!DOCTYPE html>" -msgstr "" - -#. module: im_livechat -#: model:ir.ui.view,arch_db:im_livechat.loader -msgid ");\n" -" button.appendTo($('body'));\n" -" window.livechat_button = button;\n" -" });\n" -" });" -msgstr "" - #. module: im_livechat #: model:ir.model.fields,help:im_livechat.field_im_livechat_channel_rule_action msgid "* Select 'Display the button' to simply display the chat button on the pages.\n" @@ -87,11 +60,17 @@ msgstr "" #. module: im_livechat #. openerp-web -#: code:addons/im_livechat/static/src/js/im_livechat.js:26 +#: code:addons/im_livechat/static/src/js/im_livechat.js:27 #, python-format msgid "Ask something ..." msgstr "" +#. module: im_livechat +#: model:ir.ui.view,arch_db:im_livechat.mail_channel_view_form +#: model:ir.ui.view,arch_db:im_livechat.mail_channel_view_tree +msgid "Attendees" +msgstr "" + #. module: im_livechat #: selection:im_livechat.channel.rule,action:0 msgid "Auto popup" @@ -176,6 +155,7 @@ msgstr "" #. module: im_livechat #: model:ir.model.fields,field_description:im_livechat.field_im_livechat_report_channel_technical_name +#: model:ir.ui.view,arch_db:im_livechat.im_livechat_report_channel_view_search msgid "Code" msgstr "" @@ -187,7 +167,7 @@ msgstr "" #. module: im_livechat #: model:ir.ui.view,arch_db:im_livechat.im_livechat_channel_view_form -msgid "Copy and paste this code into your website, within the &lt;head&gt; tag:" +msgid "Copy and paste this code into your website, within the <head> tag:" msgstr "" #. module: im_livechat @@ -290,26 +270,16 @@ msgstr "" #. module: im_livechat #. openerp-web -#: code:addons/im_livechat/static/src/xml/im_livechat.xml:16 +#: code:addons/im_livechat/static/src/xml/im_livechat.xml:19 #, python-format msgid "Explain your note" msgstr "" -#. module: im_livechat -#: model:ir.ui.view,arch_db:im_livechat.mail_channel_view_form -msgid "Feedback" -msgstr "" - #. module: im_livechat #: model:ir.ui.view,arch_db:im_livechat.im_livechat_channel_view_form msgid "For website built with Odoo CMS, please install the website_livechat module. Then go to Settings > Website Settings and select the Website Live Chat Channel you want to add on your website." msgstr "" -#. module: im_livechat -#: model:ir.ui.view,arch_db:im_livechat.mail_channel_view_form -msgid "General" -msgstr "" - #. module: im_livechat #: model:ir.model.fields,help:im_livechat.field_im_livechat_channel_rule_sequence msgid "Given the order to find a matching rule. If 2 rules are matching for the given url/country, the one with the lowest sequence will be chosen." @@ -361,9 +331,9 @@ msgstr "" #. module: im_livechat #. openerp-web -#: code:addons/im_livechat/static/src/js/im_livechat.js:220 +#: code:addons/im_livechat/static/src/xml/im_livechat.xml:15 #, python-format -msgid "I rated you with :rating_%d" +msgid "I don't want to rate this conversation" msgstr "" #. module: im_livechat @@ -449,11 +419,6 @@ msgstr "" msgid "Livechat Support Channel Statistics allows you to easily check and analyse your company livechat session performance. Extract informations about the missed sessions, the audiance, the duration of a session, etc." msgstr "" -#. module: im_livechat -#: model:ir.ui.view,arch_db:im_livechat.support_page -msgid "Livechat Support Page" -msgstr "" - #. module: im_livechat #: model:ir.model,name:im_livechat.model_im_livechat_report_channel #: model:ir.model,name:im_livechat.model_im_livechat_report_operator @@ -579,6 +544,11 @@ msgstr "" msgid "Options" msgstr "" +#. module: im_livechat +#: model:ir.model.fields,help:im_livechat.field_im_livechat_channel_rating_percentage_satisfaction +msgid "Percentage of happy ratings over the past 7 days" +msgstr "" + #. module: im_livechat #: model:ir.ui.view,arch_db:im_livechat.im_livechat_channel_view_kanban msgid "Quit" @@ -590,6 +560,13 @@ msgstr "" msgid "Rating" msgstr "" +#. module: im_livechat +#. openerp-web +#: code:addons/im_livechat/static/src/js/im_livechat.js:308 +#, python-format +msgid "Rating: :rating_%d" +msgstr "" + #. module: im_livechat #: model:ir.model.fields,help:im_livechat.field_im_livechat_channel_rule_regex_url msgid "Regular expression identifying the web page on which the rules will be applied." @@ -623,8 +600,9 @@ msgid "Search report" msgstr "" #. module: im_livechat -#: model:ir.ui.view,arch_db:im_livechat.im_livechat_report_channel_view_search -msgid "Session" +#: model:ir.ui.view,arch_db:im_livechat.mail_channel_view_form +#: model:ir.ui.view,arch_db:im_livechat.mail_channel_view_tree +msgid "Session Date" msgstr "" #. module: im_livechat @@ -777,11 +755,6 @@ msgid "You can create channels for each website on which you want\n" " visitors to talk in real time with your operators." msgstr "" -#. module: im_livechat -#: model:ir.ui.view,arch_db:im_livechat.loader -msgid "document.addEventListener(\"DOMContentLoaded\", function(event) {" -msgstr "" - #. module: im_livechat #: model:ir.ui.view,arch_db:im_livechat.im_livechat_channel_view_form msgid "e.g. Hello, how may I help you?" @@ -792,30 +765,6 @@ msgstr "" msgid "e.g. YourWebsite.com" msgstr "" -#. module: im_livechat -#. openerp-web -#: code:addons/im_livechat/static/src/xml/im_livechat_backend.xml:6 -#, python-format -msgid "livechat" -msgstr "" - -#. module: im_livechat -#: model:ir.ui.view,arch_db:im_livechat.loader -msgid "odoo.define('im_livechat.livesupport', function (require) {\n" -" var im_livechat = require('im_livechat.im_livechat');\n" -" var button = new im_livechat.LivechatButton(\n" -" $('body'),\n" -" \"" -msgstr "" - -#. module: im_livechat -#: model:ir.ui.view,arch_db:im_livechat.loader -msgid "odoo.define('web.session', function (require) {\n" -" var Session = require('web.Session');\n" -" var modules = odoo._modules;\n" -" return new Session(undefined, \"" -msgstr "" - #. module: im_livechat #: model:ir.ui.view,arch_db:im_livechat.im_livechat_channel_view_form msgid "or copy this url and send it by email to your customers or suppliers:" @@ -826,11 +775,3 @@ msgstr "" msgid "seconds" msgstr "" -#. module: im_livechat -#. openerp-web -#: code:addons/im_livechat/static/src/xml/im_livechat_backend.xml:9 -#: code:addons/im_livechat/static/src/xml/im_livechat_backend.xml:12 -#, python-format -msgid "true" -msgstr "" -