diff --git a/mail_activity/__init__.py b/mail_activity/__init__.py index 45d83e10..a0fdc10f 100644 --- a/mail_activity/__init__.py +++ b/mail_activity/__init__.py @@ -1,4 +1,2 @@ # -*- coding: utf-8 -*- from . import models -from . import wizards -from .hooks import post_load_hook \ No newline at end of file diff --git a/mail_activity/__openerp__.py b/mail_activity/__manifest__.py similarity index 96% rename from mail_activity/__openerp__.py rename to mail_activity/__manifest__.py index 96af1de3..da24c26b 100644 --- a/mail_activity/__openerp__.py +++ b/mail_activity/__manifest__.py @@ -19,6 +19,7 @@ "data/mail_message_subtype.xml", 'security/ir.model.access.csv', 'views/mail_activity.xml', + 'views/crm_action_views.xml', 'data/mail_activity.xml', 'data/ir_model_data.xml', 'views/templates.xml', @@ -28,5 +29,4 @@ 'static/src/xml/systray.xml', 'static/src/xml/web_kanban_activity.xml', ], - "post_load": "post_load_hook", } diff --git a/mail_activity/hooks.py b/mail_activity/hooks.py deleted file mode 100644 index 55252ce4..00000000 --- a/mail_activity/hooks.py +++ /dev/null @@ -1,124 +0,0 @@ -# Copyright 2018 Eficent Business and IT Consulting Services S.L. -# Copyright 2018 Odoo, S.A. -# License AGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). - -from openerp.addons.mail.wizard.mail_compose_message import MailComposer - - -def post_load_hook(): - """ - We need this hook only in v9 in order to be able to capture the subtype. - - """ - def new_send_mail(self, auto_commit=False): - - if 'subtype_id' not in self._fields: - return self.send_mail_original(auto_commit=auto_commit) - - """ Process the wizard content and proceed with sending the related - email(s), rendering any template patterns on the fly - if needed. """ - for wizard in self: - # Duplicate attachments linked to the email.template. - # Indeed, basic mail.compose.message wizard duplicates - # attachments in mass - # mailing mode. But in 'single post' mode, attachments of - # an email template - # also have to be duplicated to avoid changing their ownership. - if wizard.attachment_ids and \ - wizard.composition_mode != 'mass_mail' and \ - wizard.template_id: - new_attachment_ids = [] - for attachment in wizard.attachment_ids: - if attachment in wizard.template_id.attachment_ids: - new_attachment_ids.append(attachment.copy( - {'res_model': 'mail.compose.message', - 'res_id': wizard.id}).id) - else: - new_attachment_ids.append(attachment.id) - wizard.write({'attachment_ids': [(6, 0, - new_attachment_ids)]}) - - # Mass Mailing - mass_mode = wizard.composition_mode in ('mass_mail', 'mass_post') - - Mail = self.env['mail.mail'] - ActiveModel = self.env[ - wizard.model if wizard.model else 'mail.thread'] - if wizard.template_id: - # template user_signature is added when generating body_html - # mass mailing: use template auto_delete value -> note, - # for emails mass mailing only - Mail = Mail.with_context(mail_notify_user_signature=False) - ActiveModel = ActiveModel.with_context( - mail_notify_user_signature=False, - mail_auto_delete=wizard.template_id.auto_delete) - if not hasattr(ActiveModel, 'message_post'): - ActiveModel = self.env['mail.thread'].with_context( - thread_model=wizard.model) - if wizard.composition_mode == 'mass_post': - # do not send emails directly but use the queue instead - # add context key to avoid subscribing the author - ActiveModel = ActiveModel.with_context( - mail_notify_force_send=False, - mail_create_nosubscribe=True) - # wizard works in batch mode: [res_id] or - # active_ids or active_domain - if mass_mode and wizard.use_active_domain and wizard.model: - res_ids = self.env[wizard.model].search( - eval(wizard.active_domain)).ids - elif mass_mode and wizard.model and self._context.get( - 'active_ids'): - res_ids = self._context['active_ids'] - else: - res_ids = [wizard.res_id] - - batch_size = int(self.env['ir.config_parameter'].sudo().get_param( - 'mail.batch_size')) or self._batch_size - sliced_res_ids = [res_ids[i:i + batch_size] for i in - range(0, len(res_ids), batch_size)] - - # ---- START OF PATCH - if wizard.composition_mode == 'mass_mail' or wizard.is_log or ( - wizard.composition_mode == 'mass_post' - and not wizard.notify): # log a note: subtype is False - subtype_id = False - elif wizard.subtype_id: - subtype_id = wizard.subtype_id - else: - subtype_id = self.sudo().env.ref('mail.mt_comment', - raise_if_not_found=False) - if subtype_id: - external_subtype = subtype_id.get_external_id() - if external_subtype: - subtype = external_subtype[subtype_id.id] - else: - subtype = 'mail.mt_comment' - # ---- END OF PATCH - - for res_ids in sliced_res_ids: - batch_mails = Mail - all_mail_values = wizard.get_mail_values(res_ids) - for res_id, mail_values in all_mail_values.iteritems(): - if wizard.composition_mode == 'mass_mail': - batch_mails |= Mail.create(mail_values) - else: - # subtype = 'mail.mt_comment' -> Removed - if wizard.is_log or ( - wizard.composition_mode == 'mass_post' - and not wizard.notify): # log a note: - # subtype is False - subtype = False - ActiveModel.browse(res_id).message_post( - message_type='comment', subtype=subtype, - **mail_values) - - if wizard.composition_mode == 'mass_mail': - batch_mails.send(auto_commit=auto_commit) - - return {'type': 'ir.actions.act_window_close'} - - if not hasattr(MailComposer, 'send_mail_original'): - MailComposer.send_mail_original = MailComposer.send_mail - - MailComposer.send_mail = new_send_mail diff --git a/mail_activity/models/__init__.py b/mail_activity/models/__init__.py index cdddcb46..84c2103c 100644 --- a/mail_activity/models/__init__.py +++ b/mail_activity/models/__init__.py @@ -4,4 +4,5 @@ from . import mail_activity_mixin from . import mail_activity from . import res_partner from . import mail_message +from . import mail_compose_message from . import res_users diff --git a/mail_activity/models/mail_activity.py b/mail_activity/models/mail_activity.py index 777f6ac1..238ab924 100644 --- a/mail_activity/models/mail_activity.py +++ b/mail_activity/models/mail_activity.py @@ -3,30 +3,7 @@ # Copyright 2018 Eficent # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). from datetime import date, datetime, timedelta -from openerp import api, fields, models - - -def message_post_with_view(records, views_or_xmlid, **kwargs): - """ Method ported from mail.thread in v10 """ - values = kwargs.pop('values', None) or dict() - try: - from openerp.addons.website.models.website import slug - values['slug'] = slug - except ImportError: - values['slug'] = lambda self: self.id - if isinstance(views_or_xmlid, basestring): - views = records.env.ref(views_or_xmlid, raise_if_not_found=False) - else: - views = views_or_xmlid - if not views: - return - for record in records: - values['object'] = record - rendered_template = views.render(values, engine='ir.qweb') - kwargs['body'] = rendered_template - kwargs['message_type'] = 'notification' # default in v10 - kwargs['subtype_id'] = record.env.ref('mail.mt_activities').id, - record.message_post_with_template(False, **kwargs) +from odoo import api, fields, models class MailActivity(models.Model): @@ -212,8 +189,7 @@ class MailActivity(models.Model): self.write(dict(feedback=feedback)) for activity in self: record = self.env[activity.res_model].browse(activity.res_id) - message_post_with_view( - record, + record.message_post_with_view( 'mail.message_activity_done', values={'activity': activity}, subtype_id=self.env.ref('mail.mt_activities').id, diff --git a/mail_activity/models/mail_activity_mixin.py b/mail_activity/models/mail_activity_mixin.py index d32beda4..e7513645 100644 --- a/mail_activity/models/mail_activity_mixin.py +++ b/mail_activity/models/mail_activity_mixin.py @@ -3,19 +3,19 @@ # Copyright 2018 Therp BV # Copyright 2018 Eficent # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). -from openerp import api, fields +from odoo import api, fields, models -def setup_mail_actitivities(cls): - """ Mixin using AbstractModels are problematic in Odoo v9, since they - prevent the new-style computed fields from working correctly. - This decorator edits the original class in-place, so the Odoo model - is left unchanged. """ - cls.activity_ids = fields.One2many( +class MailActivityMixin(models.AbstractModel): + + _name = 'mail.activity.mixin' + _description = 'Activity Mixin' + + activity_ids = fields.One2many( 'mail.activity', 'res_id', 'Activities', auto_join=True, domain=lambda self: [('res_model', '=', self._name)]) - cls.activity_state = fields.Selection([ + activity_state = fields.Selection([ ('overdue', 'Overdue'), ('today', 'Today'), ('planned', 'Planned')], string='State', @@ -23,27 +23,26 @@ def setup_mail_actitivities(cls): help='Status based on activities\n' 'Overdue: Due date is already passed\n' 'Today: Activity date is today\nPlanned: Future activities.') - cls.activity_user_id = fields.Many2one( + activity_user_id = fields.Many2one( 'res.users', 'Responsible', related='activity_ids.user_id', search='_search_activity_user_id') - cls.activity_type_id = fields.Many2one( + activity_type_id = fields.Many2one( 'mail.activity.type', 'Next Activity Type', related='activity_ids.activity_type_id', search='_search_activity_type_id') - cls.activity_date_deadline = fields.Date( + activity_date_deadline = fields.Date( 'Next Activity Deadline', related='activity_ids.date_deadline', readonly=True, store=True) # store to enable ordering + search - cls.activity_summary = fields.Char( + activity_summary = fields.Char( 'Next Activity Summary', related='activity_ids.summary', search='_search_activity_summary') - cls.nbr_activities = fields.Integer(compute='_compute_nbr_activities') + nbr_activities = fields.Integer(compute='_compute_nbr_activities') @api.depends('activity_ids') def _compute_nbr_activities(self): for record in self: record.nbr_activities = len(record.activity_ids) - cls._compute_nbr_activities = _compute_nbr_activities @api.depends('activity_ids.state') def _compute_activity_state(self): @@ -55,35 +54,26 @@ def setup_mail_actitivities(cls): record.activity_state = 'today' elif 'planned' in states: record.activity_state = 'planned' - cls._compute_activity_state = _compute_activity_state @api.model def _search_activity_user_id(self, operator, operand): return [('activity_ids.user_id', operator, operand)] - cls._search_activity_user_id = _search_activity_user_id @api.model def _search_activity_type_id(self, operator, operand): return [('activity_ids.activity_type_id', operator, operand)] - cls._search_activity_type_id = _search_activity_type_id @api.model def _search_activity_summary(self, operator, operand): return [('activity_ids.summary', operator, operand)] - cls._search_activity_summary = _search_activity_summary - - original_unlink = cls.unlink @api.multi def unlink(self): """ Override unlink to delete records activities through (res_model, res_id). """ record_ids = self.ids - result = original_unlink(self) + result = super(MailActivityMixin, self).unlink() self.env['mail.activity'].sudo().search( [('res_model', '=', self._name), ('res_id', 'in', record_ids)] ).unlink() return result - cls.unlink = unlink - - return cls diff --git a/mail_activity/models/mail_activity_type.py b/mail_activity/models/mail_activity_type.py index 3ba9d63b..f3da35f4 100644 --- a/mail_activity/models/mail_activity_type.py +++ b/mail_activity/models/mail_activity_type.py @@ -3,7 +3,7 @@ # Copyright 2018 Therp BV # Copyright 2018 Eficent # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). -from openerp import fields, models +from odoo import fields, models class MailActivityType(models.Model): diff --git a/mail_activity/models/mail_compose_message.py b/mail_activity/models/mail_compose_message.py new file mode 100644 index 00000000..a9a8427b --- /dev/null +++ b/mail_activity/models/mail_compose_message.py @@ -0,0 +1,15 @@ +from odoo import api, fields, models + + +class MailComposeMessage(models.TransientModel): + _inherit = 'mail.compose.message' + + @api.multi + def get_mail_values(self, res_ids): + """Generate the values that will be used by send_mail to create mail_messages + or mail_mails. """ + results = super(MailComposeMessage, self).get_mail_values(res_ids) + + for res_id in res_ids: + results[res_id]['mail_activity_type_id'] = self.mail_activity_type_id.id + return results diff --git a/mail_activity/models/mail_message.py b/mail_activity/models/mail_message.py index 98b797e9..317f075b 100644 --- a/mail_activity/models/mail_message.py +++ b/mail_activity/models/mail_message.py @@ -3,7 +3,7 @@ # Copyright 2018 Therp BV # Copyright 2018 Eficent # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). -from openerp import fields, models +from odoo import fields, models class MailMessage(models.Model): diff --git a/mail_activity/models/res_partner.py b/mail_activity/models/res_partner.py index 2dec1663..7af329f8 100644 --- a/mail_activity/models/res_partner.py +++ b/mail_activity/models/res_partner.py @@ -2,10 +2,9 @@ # Copyright 2016 Odoo SA # Copyright 2018 Therp BV # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). -from openerp import models -from .mail_activity_mixin import setup_mail_actitivities +from odoo import models -@setup_mail_actitivities class ResPartner(models.Model): - _inherit = 'res.partner' + _name = 'res.partner' + _inherit = ['res.partner', 'mail.activity.mixin'] diff --git a/mail_activity/models/res_users.py b/mail_activity/models/res_users.py index bd0f1cb7..5b89aaca 100644 --- a/mail_activity/models/res_users.py +++ b/mail_activity/models/res_users.py @@ -3,7 +3,7 @@ # Copyright 2018 Therp BV # Copyright 2018 Eficent # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). -from openerp import api, fields, models, modules +from odoo import api, fields, models, modules class ResUsers(models.Model): diff --git a/mail_activity/static/src/less/systray.less b/mail_activity/static/src/less/systray.less index 74be7be8..68bfc6a7 100644 --- a/mail_activity/static/src/less/systray.less +++ b/mail_activity/static/src/less/systray.less @@ -1,7 +1,7 @@ @gray-lighter-darker: #d9d7d7; @gray-lighter-dark: #E5E5E5; // Navbar icon and dropdown -.o_mail_navbar_item { +.o_mail_navbar_item_v10 { > a { opacity: 1; > i { @@ -19,7 +19,7 @@ .o-flex-flow(column, nowrap); } .o_notification_counter { - .o-position-absolute(@top: 20%, @right: 1px); + .o-position-absolute(@top: 20%, @right: -3px); background: @odoo-brand-optional; color: white; padding: 0em 0.3em; diff --git a/mail_activity/static/src/xml/systray.xml b/mail_activity/static/src/xml/systray.xml index b05f756d..f7304559 100644 --- a/mail_activity/static/src/xml/systray.xml +++ b/mail_activity/static/src/xml/systray.xml @@ -32,7 +32,7 @@ -
  • +
  • diff --git a/mail_activity/tests/test_mail_activity.py b/mail_activity/tests/test_mail_activity.py index a6cdf60b..ed6e88c3 100644 --- a/mail_activity/tests/test_mail_activity.py +++ b/mail_activity/tests/test_mail_activity.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- # © 2017 Therp BV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp import fields -from openerp.tests.common import TransactionCase +from odoo import fields +from odoo.tests.common import TransactionCase class TestMailActivity(TransactionCase): diff --git a/mail_activity_crm/views/crm_action_views.xml b/mail_activity/views/crm_action_views.xml similarity index 100% rename from mail_activity_crm/views/crm_action_views.xml rename to mail_activity/views/crm_action_views.xml diff --git a/mail_activity/wizards/__init__.py b/mail_activity/wizards/__init__.py deleted file mode 100644 index 12ddb2dc..00000000 --- a/mail_activity/wizards/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# -*- coding: utf-8 -*- -from . import mail_compose_message diff --git a/mail_activity/wizards/mail_compose_message.py b/mail_activity/wizards/mail_compose_message.py deleted file mode 100644 index 8dd895cd..00000000 --- a/mail_activity/wizards/mail_compose_message.py +++ /dev/null @@ -1,12 +0,0 @@ -# -*- coding: utf-8 -*- -from openerp import fields, models - - -class MailComposer(models.TransientModel): - - _inherit = 'mail.compose.message' - - # This field is already in v10 onwards. - subtype_id = fields.Many2one( - default=lambda self: self.sudo().env.ref('mail.mt_comment', - raise_if_not_found=False).id) diff --git a/mail_activity_calendar/__openerp__.py b/mail_activity_calendar/__manifest__.py similarity index 100% rename from mail_activity_calendar/__openerp__.py rename to mail_activity_calendar/__manifest__.py diff --git a/mail_activity_crm/__openerp__.py b/mail_activity_crm/__manifest__.py similarity index 89% rename from mail_activity_crm/__openerp__.py rename to mail_activity_crm/__manifest__.py index 93d7db90..b7f688d3 100644 --- a/mail_activity_crm/__openerp__.py +++ b/mail_activity_crm/__manifest__.py @@ -17,9 +17,7 @@ ], "data": [ "views/crm_lead_views.xml", - 'views/crm_activity_report_view.xml', 'views/crm_lead_menu.xml', - 'views/crm_action_views.xml', ], 'post_init_hook': 'post_init_hook', } diff --git a/mail_activity_crm/hooks.py b/mail_activity_crm/hooks.py index 1ee6f3f5..fc94693a 100644 --- a/mail_activity_crm/hooks.py +++ b/mail_activity_crm/hooks.py @@ -1,7 +1,7 @@ # Copyright 2018 Eficent Business and IT Consulting Services S.L. # Copyright 2018 Tecnativa, S.L. # License AGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). -from openerp import api, SUPERUSER_ID +from odoo import api, SUPERUSER_ID def convert_crm_activity_types(env): @@ -72,7 +72,7 @@ def convert_crm_lead_activities(env): SELECT cl.id, im.id, 'crm.lead', cl.name, cl.title_action, mat.id, cl.date_action, cl.create_uid, cl.create_date, - cl.write_uid, cl.write_date, COALESCE(cl.user_id, cl.create_uid) + cl.write_uid, cl.write_date, COALESCE(cl.user_id, cl.create_uid, 1) FROM crm_lead AS cl, mail_activity_type AS mat, diff --git a/mail_activity_crm/models/__init__.py b/mail_activity_crm/models/__init__.py index 7c8a50f7..6c90d1fa 100644 --- a/mail_activity_crm/models/__init__.py +++ b/mail_activity_crm/models/__init__.py @@ -2,3 +2,5 @@ from . import crm_lead from . import calendar_event from . import mail_activity +from . import crm_activity_report_odoo_v10 +from . import crm_activity_report diff --git a/mail_activity_crm/models/calendar_event.py b/mail_activity_crm/models/calendar_event.py index f2320e68..7aff0ee2 100644 --- a/mail_activity_crm/models/calendar_event.py +++ b/mail_activity_crm/models/calendar_event.py @@ -3,7 +3,7 @@ # Copyright 2018 Therp BV # Copyright 2018 Eficent # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). -from openerp import api, models +from odoo import api, models class CalendarEvent(models.Model): diff --git a/mail_activity_crm/models/crm_activity_report.py b/mail_activity_crm/models/crm_activity_report.py new file mode 100644 index 00000000..f7876e5f --- /dev/null +++ b/mail_activity_crm/models/crm_activity_report.py @@ -0,0 +1,19 @@ +from odoo import api, fields, models + + +class CrmActivityReport(models.Model): + _inherit = 'crm.activity.report' + + mail_activity_type_id = fields.Many2one('mail.activity.type', 'Activity Type', readonly=True) + + def _select(self): + select = super(CrmActivityReport, self)._select() + return select + """ + , m.mail_activity_type_id + """ + + def _where(self): + where = super(CrmActivityReport, self)._where() + return where + """ + -- AND m.mail_activity_type_id IS NOT NULL + """ diff --git a/mail_activity_crm/models/crm_activity_report_odoo_v10.py b/mail_activity_crm/models/crm_activity_report_odoo_v10.py new file mode 100644 index 00000000..414d5607 --- /dev/null +++ b/mail_activity_crm/models/crm_activity_report_odoo_v10.py @@ -0,0 +1,56 @@ +from odoo import tools, api, fields, models + +# Copy Odoo's implementation in v12 back to v10 so that we have useful hooks to add what we need to later on. + + +class CrmActivityReportOdoo(models.Model): + _inherit = 'crm.activity.report' + + def _select(self): + return """ + SELECT + m.id, + m.subtype_id, + m.author_id, + m.date, + m.subject, + l.id as lead_id, + l.user_id, + l.team_id, + l.country_id, + l.company_id, + l.stage_id, + l.partner_id, + l.type as lead_type, + l.active, + l.probability + """ + + def _from(self): + return """ + FROM mail_message AS m + """ + + def _join(self): + return """ + JOIN crm_lead AS l ON m.res_id = l.id + """ + + def _where(self): + return """ + WHERE + m.model = 'crm.lead' + """ + + @api.model_cr + def init(self): + tools.drop_view_if_exists(self._cr, self._table) + self._cr.execute(""" + CREATE OR REPLACE VIEW %s AS ( + %s + %s + %s + %s + ) + """ % (self._table, self._select(), self._from(), self._join(), self._where()) + ) diff --git a/mail_activity_crm/models/crm_lead.py b/mail_activity_crm/models/crm_lead.py index 3cfcf424..11bbc77e 100644 --- a/mail_activity_crm/models/crm_lead.py +++ b/mail_activity_crm/models/crm_lead.py @@ -3,11 +3,9 @@ # Copyright 2018 Therp BV # Copyright 2018 Eficent # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). -from openerp import models -from openerp.addons.mail_activity.models.mail_activity_mixin import \ - setup_mail_actitivities +from odoo import models -@setup_mail_actitivities class CrmLead(models.Model): - _inherit = 'crm.lead' + _name = 'crm.lead' + _inherit = ['crm.lead', 'mail.activity.mixin'] \ No newline at end of file diff --git a/mail_activity_crm/models/mail_activity.py b/mail_activity_crm/models/mail_activity.py index 4a5787aa..e2d8b232 100644 --- a/mail_activity_crm/models/mail_activity.py +++ b/mail_activity_crm/models/mail_activity.py @@ -3,7 +3,7 @@ # Copyright 2018 Therp BV # Copyright 2018 Eficent # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). -from openerp import api, models +from odoo import api, models class MailActivity(models.Model): diff --git a/mail_activity_crm/views/crm_activity_report_view.xml b/mail_activity_crm/views/crm_activity_report_view.xml deleted file mode 100644 index 4e1386ff..00000000 --- a/mail_activity_crm/views/crm_activity_report_view.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - Activities (obsolete) - - - - diff --git a/mail_activity_crm/views/crm_lead_menu.xml b/mail_activity_crm/views/crm_lead_menu.xml index dd756090..e7b272d9 100644 --- a/mail_activity_crm/views/crm_lead_menu.xml +++ b/mail_activity_crm/views/crm_lead_menu.xml @@ -1,5 +1,5 @@ - + @@ -8,4 +8,4 @@ - +