From dde1404cb9ce538cc1216c9256f0f5c1e74ecc06 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Mon, 25 Apr 2016 18:00:01 +0200 Subject: [PATCH 1/8] [FIX] sale: Teams dashboard, sales to invoice count From 9.0, a sales order to invoice is no longer a sales order in the state `manual`, but with the Invoice Status "to invoice". Before this revision, the sales order to invoice were simply not counted at all, and this count always displayed 0. opw-675919 --- addons/sale/sales_team.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sale/sales_team.py b/addons/sale/sales_team.py index c4a593cf11d..309419eb97f 100644 --- a/addons/sale/sales_team.py +++ b/addons/sale/sales_team.py @@ -18,7 +18,7 @@ class crm_team(osv.Model): res = dict.fromkeys(ids, 0) domain = [ ('team_id', 'in', ids), - ('state', '=', 'manual'), + ('invoice_status', '=', 'to invoice'), ] amounts = obj.read_group(cr, uid, domain, ['amount_total', 'team_id'], ['team_id'], context=context) for rec in amounts: From e1ed2c6ddc6750a2090ee37badfaeccadd765b9b Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Mon, 25 Apr 2016 14:01:01 +0200 Subject: [PATCH 2/8] [FIX] mail: visibility rules for channel notifications Avoid raising an access denied error for messages that the user has indeed be notified about. The issue arose when a message posted on a document inaccessible to the user was notified to one of the channels the user is subscribed to. The access control logic on messages relies on 2 heuristics to grant read access to a message: a. either the user was notified about the messages, by being a follower of the document, or a subscriber of a channel following the document (in that case the user can see the message but not the document) b. or the user has read access to the document on which the message is posted (in that case the user can see both the message and the document) Case `a.` sometimes fail to match when a message got notified to several channels including one the user was not subscribed to. Depending on the order of the returned rows in the SQL query, the "foreign" channels could shadow the channels of the user, making `a.` a non-match. If case `b.` did not match either, the user would have the `read` access denied, even though the message was visible by the `search()` method. The fix explicitly makes case `a.` match if the user was notified in *at least* one channel. This was not done through a change of the SQL query ORDER, for readability reasons. --- addons/mail/models/mail_message.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/addons/mail/models/mail_message.py b/addons/mail/models/mail_message.py index fe7d6d88448..f86ba64ce7e 100644 --- a/addons/mail/models/mail_message.py +++ b/addons/mail/models/mail_message.py @@ -741,7 +741,13 @@ class Message(models.Model): ON channel_partner.channel_id = channel.id AND channel_partner.partner_id = (%%s) WHERE m.id = ANY (%%s)""" % self._table, (self.env.user.partner_id.id, self.env.user.partner_id.id, self.ids,)) for mid, rmod, rid, author_id, parent_id, partner_id, channel_id in self._cr.fetchall(): - message_values[mid] = {'model': rmod, 'res_id': rid, 'author_id': author_id, 'parent_id': parent_id, 'partner_id': partner_id, 'channel_id': channel_id} + message_values[mid] = { + 'model': rmod, + 'res_id': rid, + 'author_id': author_id, + 'parent_id': parent_id, + 'notified': any((message_values[mid].get('notified'), partner_id, channel_id)) + } else: self._cr.execute("""SELECT DISTINCT id, model, res_id, author_id, parent_id FROM "%s" WHERE id = ANY (%%s)""" % self._table, (self.ids,)) for mid, rmod, rid, author_id, parent_id in self._cr.fetchall(): @@ -780,7 +786,7 @@ class Message(models.Model): other_ids = set(self.ids).difference(set(author_ids), set(notified_ids)) model_record_ids = _generate_model_record_ids(message_values, other_ids) if operation in ['read', 'write']: - notified_ids = [mid for mid, message in message_values.iteritems() if message.get('partner_id') or message.get('channel_id')] + notified_ids = [mid for mid, message in message_values.iteritems() if message.get('notified')] elif operation == 'create': for doc_model, doc_ids in model_record_ids.items(): followers = self.env['mail.followers'].sudo().search([ From ccd7a157092c9b9d7708c14b9d263d47a92f233b Mon Sep 17 00:00:00 2001 From: Damien Bouvy Date: Mon, 25 Apr 2016 18:28:01 +0200 Subject: [PATCH 3/8] [FIX] base: fixes previous fix In fix e248882, the previous elif statement prevented the execution of the fix code. This fix fixes the fix. --- openerp/addons/base/ir/ir_http.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/ir/ir_http.py b/openerp/addons/base/ir/ir_http.py index 5148b11c8d8..e04bd270eea 100644 --- a/openerp/addons/base/ir/ir_http.py +++ b/openerp/addons/base/ir/ir_http.py @@ -300,7 +300,7 @@ class ir_http(osv.AbstractModel): mimetype = obj.mimetype elif filename: mimetype = mimetypes.guess_type(filename)[0] - elif getattr(env[model]._fields[field], 'attachment', False): + if not mimetype and getattr(env[model]._fields[field], 'attachment', False): # for binary fields, fetch the ir_attachement for mimetype check attach_mimetype = env['ir.attachment'].search_read(domain=[('res_model', '=', model), ('res_id', '=', id), ('res_field', '=', field)], fields=['mimetype'], limit=1) mimetype = attach_mimetype and attach_mimetype[0]['mimetype'] From a84342441d80ac1da03417ca0a40ab2fb225b9b2 Mon Sep 17 00:00:00 2001 From: Damien Bouvy Date: Tue, 26 Apr 2016 09:35:10 +0200 Subject: [PATCH 4/8] [FIX] hr_recruitment: no create on ir_attachment action The "Resumes and Letters" action simply displays ir_attachments linked to hr_applicant objects; but there is no default_res_model in the context so no ir_attachment you create is actually displayed in the kanban view. Since the goal of this action is simply to display attachments linked to applicants, it makes more sense to disable the create button and to force people to upload resumes and cover letters through the applicant record. --- addons/hr_recruitment/views/hr_recruitment_views.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/hr_recruitment/views/hr_recruitment_views.xml b/addons/hr_recruitment/views/hr_recruitment_views.xml index 4926c8f3003..ec8b246ff62 100644 --- a/addons/hr_recruitment/views/hr_recruitment_views.xml +++ b/addons/hr_recruitment/views/hr_recruitment_views.xml @@ -559,6 +559,7 @@ kanban,tree,form [('res_model','=','hr.applicant')] + {'create': False}

Search through resumes and motivation letters. From 9d14230d74ecc4ebf07d8e9f264bfbe066c17ff0 Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Mon, 25 Apr 2016 17:11:34 +0200 Subject: [PATCH 5/8] [FIX] account_asset: asset_create When creating assets from invoice lines, the system must check that assets have not already been created for the related invoice. If assets already exist then these assets have to be removed. Used case: - In the purchase journal, tick "allow canceling entries" - On a supplier invoice line, set an asset category - validate the invoice - cancel the invoice - set to draft - validate the invoice Before the fix: the asset is created twice. After the fix: the asset is created once. opw:674674 --- addons/account_asset/account_asset_invoice.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/account_asset/account_asset_invoice.py b/addons/account_asset/account_asset_invoice.py index 88027ca8125..76283257aae 100644 --- a/addons/account_asset/account_asset_invoice.py +++ b/addons/account_asset/account_asset_invoice.py @@ -17,8 +17,9 @@ class AccountInvoice(models.Model): result = super(AccountInvoice, self).action_move_create() for inv in self: if inv.number: - if self.env['account.asset.asset'].sudo().search([('code', '=', inv.number)]): - raise Warning(_('You already have assets with the reference %s.\nPlease delete these assets before creating new ones for this invoice.') % (inv.number,)) + asset_ids = self.env['account.asset.asset'].sudo().search([('invoice_id', '=', inv.id), ('company_id', '=', inv.company_id.id)]) + if asset_ids: + asset_ids .write({'active': False}) inv.invoice_line_ids.asset_create() return result From 58a5b5e453e39f1e334f4d7d4a89c9c4e3a790c2 Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Tue, 26 Apr 2016 11:30:55 +0200 Subject: [PATCH 6/8] [FIX] account_asset: Typo error --- addons/account_asset/account_asset_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/account_asset/account_asset_invoice.py b/addons/account_asset/account_asset_invoice.py index 76283257aae..8e8187b93bf 100644 --- a/addons/account_asset/account_asset_invoice.py +++ b/addons/account_asset/account_asset_invoice.py @@ -19,7 +19,7 @@ class AccountInvoice(models.Model): if inv.number: asset_ids = self.env['account.asset.asset'].sudo().search([('invoice_id', '=', inv.id), ('company_id', '=', inv.company_id.id)]) if asset_ids: - asset_ids .write({'active': False}) + asset_ids.write({'active': False}) inv.invoice_line_ids.asset_create() return result From 02fd74a3faa248483bdc6b4ca9fd0b4dc05557bc Mon Sep 17 00:00:00 2001 From: David Monjoie Date: Tue, 26 Apr 2016 11:16:37 +0200 Subject: [PATCH 7/8] [FIX] website_form: prevent users from crazy clicking If the feedback of a form is too slow, people might be tempted to click a second time, trigerring a second request. If, after that, the result has not been received yet, the user might be tempted to click a lot of time because he is angry at such slowness. This behavior would trigger a record creation each time the user clicked the submit button. This fix disables the button once it has been clicked once, and re-enable it if the record could not be created, which means that there was an error in the input and the user needs to change the values and try again. The button has been changed to a span to avoid the default browser behavior to post the form when no function is bound on the send button. --- addons/website_crm/views/website_crm.xml | 2 +- addons/website_form/static/src/js/website_form.js | 5 +++++ addons/website_hr_recruitment/views/templates.xml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/addons/website_crm/views/website_crm.xml b/addons/website_crm/views/website_crm.xml index db2086b07a1..fc4208a1e7e 100644 --- a/addons/website_crm/views/website_crm.xml +++ b/addons/website_crm/views/website_crm.xml @@ -44,7 +44,7 @@

- + Send
diff --git a/addons/website_form/static/src/js/website_form.js b/addons/website_form/static/src/js/website_form.js index cea891ef135..ad5dcaa5cb7 100644 --- a/addons/website_form/static/src/js/website_form.js +++ b/addons/website_form/static/src/js/website_form.js @@ -47,6 +47,7 @@ odoo.define('website_form.animation', function (require) { send: function(e) { e.preventDefault(); // Prevent the default submit behavior + this.$target.find('.o_website_form_send').off(); // Prevent users from crazy clicking var self = this; @@ -211,6 +212,10 @@ odoo.define('website_form.animation', function (require) { }, update_status: function(status) { + var self = this; + if (status != 'success') { // Restore send button behavior if result is an error + this.$target.find('.o_website_form_send').on('click',function(e) {self.send(e);}); + } this.$target.find('#o_website_form_result').replaceWith(qweb.render("website_form.status_" + status)) }, }); diff --git a/addons/website_hr_recruitment/views/templates.xml b/addons/website_hr_recruitment/views/templates.xml index 3ac6736a7e2..38643a7479e 100644 --- a/addons/website_hr_recruitment/views/templates.xml +++ b/addons/website_hr_recruitment/views/templates.xml @@ -195,7 +195,7 @@
- + Submit
From 3108a49ab20b721669c666b64140d5a26d90aeae Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Mon, 25 Apr 2016 15:07:40 +0200 Subject: [PATCH 8/8] [FIX] crm_claim: access rights for portal user The portal user is not allowed to read the crm.team model. opw:673480 --- addons/sales_team/sales_team.py | 3 ++- addons/website_project_issue/security/ir.model.access.csv | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/sales_team/sales_team.py b/addons/sales_team/sales_team.py index 93cdee60ed5..62b2163a888 100644 --- a/addons/sales_team/sales_team.py +++ b/addons/sales_team/sales_team.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from openerp import SUPERUSER_ID from openerp.osv import fields, osv @@ -16,7 +17,7 @@ class crm_team(osv.Model): context = {} if user_id is None: user_id = uid - team_ids = self.search(cr, uid, ['|', ('user_id', '=', user_id), ('member_ids', 'in', user_id)], limit=1, context=context) + team_ids = self.search(cr, SUPERUSER_ID, ['|', ('user_id', '=', user_id), ('member_ids', 'in', user_id)], limit=1, context=context) team_id = team_ids[0] if team_ids else False if not team_id and context.get('default_team_id'): team_id = context['default_team_id'] diff --git a/addons/website_project_issue/security/ir.model.access.csv b/addons/website_project_issue/security/ir.model.access.csv index e55c4c4a1cf..d84e0831aba 100644 --- a/addons/website_project_issue/security/ir.model.access.csv +++ b/addons/website_project_issue/security/ir.model.access.csv @@ -1,3 +1,2 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_issues,project_issue,project_issue.model_project_issue,base.group_portal,1,0,0,0 -access_case_section,crm_team,sales_team.model_crm_team,base.group_portal,1,0,0,0