Browse Source

Merge remote-tracking branch 'upstream/8.0' into 9.0-merge-c2b3905

pull/62/head
Ivan Yelizariev 8 years ago
parent
commit
f32ec86fc1
  1. 3
      .travis.yml
  2. 4
      mail_all/README.rst
  3. 4
      mail_all/doc/changelog.rst
  4. 4
      mail_check_immediately/doc/changelog.rst
  5. 5
      mail_fix_553/mail_fix_553.py
  6. 5
      mail_fix_empty_body/models.py
  7. 4
      mail_move_message/doc/changelog.rst
  8. 18
      mail_move_message/mail_move_message_models.py
  9. 6
      mail_outgoing/mail_outgoing_models.py
  10. 3
      mail_partner_lang/models.py
  11. 29
      mail_private/README.rst
  12. 3
      mail_private/__init__.py
  13. 35
      mail_private/__openerp__.py
  14. 7
      mail_private/doc/changelog.rst
  15. 26
      mail_private/doc/index.rst
  16. BIN
      mail_private/images/mail_private_image.png
  17. 11
      mail_private/models.py
  18. BIN
      mail_private/static/description/check_recipients.png
  19. BIN
      mail_private/static/description/icon.png
  20. 67
      mail_private/static/description/index.html
  21. BIN
      mail_private/static/description/result_message.png
  22. 201
      mail_private/static/src/js/mail_private.js
  23. 21
      mail_private/static/src/xml/mail_private.xml
  24. 15
      mail_private/template.xml
  25. 27
      mail_private/view.xml
  26. 6
      mail_recovery/README.rst
  27. 4
      mail_recovery/doc/changelog.rst
  28. 4
      mail_sent/doc/changelog.rst
  29. 1
      mail_sent/models.py
  30. 2
      res_partner_mails_count/models.py
  31. 6
      res_partner_strip_email/models.py

3
.travis.yml

@ -32,3 +32,6 @@ script:
after_success: after_success:
coveralls coveralls
notifications:
email: false

4
mail_all/README.rst

@ -9,8 +9,8 @@ Further information
HTML Description: https://apps.odoo.com/apps/modules/9.0/mail_all/ HTML Description: https://apps.odoo.com/apps/modules/9.0/mail_all/
Usage instructions: `<doc/index.rst>`__
Usage instructions: `<doc/index.rst>`___
Changelog: `<doc/changelog.rst>`__
Changelog: `<doc/changelog.rst>`___
Tested on Odoo 9.0 d3dd4161ad0598ebaa659fbd083457c77aa9448d Tested on Odoo 9.0 d3dd4161ad0598ebaa659fbd083457c77aa9448d

4
mail_all/doc/changelog.rst

@ -1,5 +1,5 @@
Changelog
=========
Updates
=======
`1.0.0` `1.0.0`
------- -------

4
mail_check_immediately/doc/changelog.rst

@ -1,7 +1,7 @@
.. _changelog: .. _changelog:
Changelog
=========
Updates
=======
`1.0.1` `1.0.1`
------- -------

5
mail_fix_553/mail_fix_553.py

@ -15,8 +15,7 @@ from openerp.tools.translate import _
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class mail_mail(osv.Model):
class MailMail(osv.Model):
_inherit = "mail.mail" _inherit = "mail.mail"
def send(self, cr, uid, ids, auto_commit=False, raise_exception=False, context=None): def send(self, cr, uid, ids, auto_commit=False, raise_exception=False, context=None):
@ -41,7 +40,7 @@ class mail_mail(osv.Model):
catchall_alias_name = self.pool['ir.config_parameter'].get_param(cr, uid, "mail.catchall.name_alias_from", context=context) catchall_alias_name = self.pool['ir.config_parameter'].get_param(cr, uid, "mail.catchall.name_alias_from", context=context)
catchall_domain = self.pool['ir.config_parameter'].get_param(cr, uid, "mail.catchall.domain", context=context) catchall_domain = self.pool['ir.config_parameter'].get_param(cr, uid, "mail.catchall.domain", context=context)
correct_email_from = '@%s>?\s*$' % catchall_domain
correct_email_from = r'@%s>?\s*$' % catchall_domain
default_email_from = '%s@%s' % (catchall_alias, catchall_domain) default_email_from = '%s@%s' % (catchall_alias, catchall_domain)
context = dict(context or {}) context = dict(context or {})

5
mail_fix_empty_body/models.py

@ -2,12 +2,11 @@
from openerp import models from openerp import models
class mail_compose_message(models.TransientModel):
class MailComposeMessage(models.TransientModel):
_inherit = 'mail.compose.message' _inherit = 'mail.compose.message'
def get_mail_values(self, cr, uid, wizard, res_ids, context=None): def get_mail_values(self, cr, uid, wizard, res_ids, context=None):
res = super(mail_compose_message, self).get_mail_values(cr, uid, wizard, res_ids, context)
res = super(MailComposeMessage, self).get_mail_values(cr, uid, wizard, res_ids, context)
for id, d in res.iteritems(): for id, d in res.iteritems():
d['body'] = d.get('body') or '' d['body'] = d.get('body') or ''
return res return res

4
mail_move_message/doc/changelog.rst

@ -1,7 +1,7 @@
.. _changelog: .. _changelog:
Changelog
=========
Updates
=======
`1.0.4` `1.0.4`
------- -------

18
mail_move_message/mail_move_message_models.py

@ -4,7 +4,7 @@ from openerp.tools import email_split
from openerp.tools.translate import _ from openerp.tools.translate import _
class wizard(models.TransientModel):
class Wizard(models.TransientModel):
_name = 'mail_move_message.wizard' _name = 'mail_move_message.wizard'
def _model_selection(self): def _model_selection(self):
@ -26,7 +26,7 @@ class wizard(models.TransientModel):
@api.model @api.model
def default_get(self, fields_list): def default_get(self, fields_list):
res = super(wizard, self).default_get(fields_list)
res = super(Wizard, self).default_get(fields_list)
model_fields = self.fields_get() model_fields = self.fields_get()
if model_fields['model']['selection']: if model_fields['model']['selection']:
@ -236,7 +236,7 @@ class wizard(models.TransientModel):
return {'type': 'ir.actions.act_window_close'} return {'type': 'ir.actions.act_window_close'}
class mail_message(models.Model):
class MailMessage(models.Model):
_inherit = 'mail.message' _inherit = 'mail.message'
is_moved = fields.Boolean('Is moved') is_moved = fields.Boolean('Is moved')
@ -308,7 +308,7 @@ class mail_message(models.Model):
r_vals['parent_id'] = r.moved_from_parent_id.id r_vals['parent_id'] = r.moved_from_parent_id.id
r_vals['res_id'] = r.moved_from_res_id r_vals['res_id'] = r.moved_from_res_id
r_vals['model'] = r.moved_from_model r_vals['model'] = r.moved_from_model
print 'update message', r, r_vals
# print 'update message', r, r_vals
if move_followers: if move_followers:
r.sudo().move_followers(r_vals.get('model'), r_vals.get('res_id')) r.sudo().move_followers(r_vals.get('model'), r_vals.get('res_id'))
r.sudo().write(r_vals) r.sudo().write(r_vals)
@ -329,7 +329,7 @@ class mail_message(models.Model):
def name_get(self, cr, uid, ids, context=None): def name_get(self, cr, uid, ids, context=None):
if not (context or {}).get('extended_name'): if not (context or {}).get('extended_name'):
return super(mail_message, self).name_get(cr, uid, ids, context=context)
return super(MailMessage, self).name_get(cr, uid, ids, context=context)
if isinstance(ids, (list, tuple)) and not len(ids): if isinstance(ids, (list, tuple)) and not len(ids):
return [] return []
if isinstance(ids, (long, int)): if isinstance(ids, (long, int)):
@ -343,7 +343,7 @@ class mail_message(models.Model):
return res return res
def _message_read_dict(self, cr, uid, message, parent_id=False, context=None): def _message_read_dict(self, cr, uid, message, parent_id=False, context=None):
res = super(mail_message, self)._message_read_dict(cr, uid, message, parent_id, context)
res = super(MailMessage, self)._message_read_dict(cr, uid, message, parent_id, context)
res['is_moved'] = message.is_moved res['is_moved'] = message.is_moved
return res return res
@ -358,7 +358,7 @@ class mail_message(models.Model):
return message_values return message_values
class mail_move_message_configuration(models.TransientModel):
class MailMoveMessageConfiguration(models.TransientModel):
_name = 'mail_move_message.config.settings' _name = 'mail_move_message.config.settings'
_inherit = 'res.config.settings' _inherit = 'res.config.settings'
@ -389,12 +389,12 @@ class mail_move_message_configuration(models.TransientModel):
config_parameters.set_param('mail_relocation_move_followers', record.move_followers or '') config_parameters.set_param('mail_relocation_move_followers', record.move_followers or '')
class res_partner(models.Model):
class ResPartner(models.Model):
_inherit = 'res.partner' _inherit = 'res.partner'
@api.model @api.model
def create(self, vals): def create(self, vals):
res = super(res_partner, self).create(vals)
res = super(ResPartner, self).create(vals)
if 'update_message_author' in self.env.context and 'email' in vals: if 'update_message_author' in self.env.context and 'email' in vals:
mail_message_obj = self.env['mail.message'] mail_message_obj = self.env['mail.message']
# Escape special SQL characters in email_address to avoid invalid matches # Escape special SQL characters in email_address to avoid invalid matches

6
mail_outgoing/mail_outgoing_models.py

@ -2,7 +2,7 @@
from openerp.osv import osv from openerp.osv import osv
class mail_message(osv.Model):
class MailMessage(osv.Model):
_inherit = 'mail.message' _inherit = 'mail.message'
def check_access_rule(self, cr, uid, ids, operation, context=None): def check_access_rule(self, cr, uid, ids, operation, context=None):
@ -13,10 +13,10 @@ class mail_message(osv.Model):
if user_groups.issuperset(group_all_emails): if user_groups.issuperset(group_all_emails):
return return
return super(mail_message, self).check_access_rule(cr, uid, ids, operation, context)
return super(MailMessage, self).check_access_rule(cr, uid, ids, operation, context)
class mail_mail(osv.Model):
class MailMail(osv.Model):
_name = 'mail.mail' _name = 'mail.mail'
_inherit = ['mail.mail', 'ir.needaction_mixin'] _inherit = ['mail.mail', 'ir.needaction_mixin']
_needaction = True _needaction = True

3
mail_partner_lang/models.py

@ -2,8 +2,7 @@
from openerp.osv import osv from openerp.osv import osv
class mail_thread(osv.Model):
class MailThread(osv.Model):
_inherit = "mail.thread" _inherit = "mail.thread"
def message_track(self, cr, uid, ids, tracked_fields, initial_values, context={}): def message_track(self, cr, uid, ids, tracked_fields, initial_values, context={}):

29
mail_private/README.rst

@ -0,0 +1,29 @@
====================
Internal Messaging
====================
Send private messages to specified recipients, regardless of who are in followers list.
Credits
=======
Contributors
------------
* Pavel Romanchenko <romanchenko@it-projects.info>
Sponsors
--------
* `IT-Projects LLC <https://it-projects.info>`__
Further information
===================
Demo: http://runbot.it-projects.info/demo/mail-addons/8.0
HTML Description: https://apps.odoo.com/apps/modules/8.0/mail_private/
Usage instructions: `<doc/index.rst>`__
Changelog: `<doc/changelog.rst>`__
Tested on Odoo 8.0 0af32f3f84bae07b11abb8538d02e35c7369a348

3
mail_private/__init__.py

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import models

35
mail_private/__openerp__.py

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
{
"name": """Internal Messaging""",
"summary": """Send private messages to specified recipients, regardless of who are in followers list.""",
"category": "Discuss",
"images": ['images/mail_private_image.png'],
"version": "1.0.0",
"application": False,
"author": "IT-Projects LLC, Pavel Romanchenko",
"website": "https://it-projects.info",
"license": "GPL-3",
"price": 90.00,
"currency": "EUR",
"depends": [
"mail",
],
"external_dependencies": {"python": [], "bin": []},
"data": [
'template.xml',
'view.xml',
],
"qweb": [
'static/src/xml/mail_private.xml',
],
"demo": [],
"post_load": None,
"pre_init_hook": None,
"post_init_hook": None,
"auto_install": False,
"installable": True,
}

7
mail_private/doc/changelog.rst

@ -0,0 +1,7 @@
Updates
=======
`1.0.0`
-------
- Init version

26
mail_private/doc/index.rst

@ -0,0 +1,26 @@
====================
Internal Messaging
====================
Installation
============
Nothing special is needed to install this module.
Usage
=====
To send a message to specified recipients:
* Click on the ``[Send internal message]``.
* Choose the recipients that should receive a message by ticking the checkboxes.
* To add more recipients click on the ``[Open the full mail composer]`` on the right upper corner of the message block and choose recipients in the **Recipient** field.
* Click on the ``[Send]`` button.
Uninstallation
==============
Nothing special is needed to uninstall this module.

BIN
mail_private/images/mail_private_image.png

After

Width: 766  |  Height: 387  |  Size: 33 KiB

11
mail_private/models.py

@ -0,0 +1,11 @@
# -*- coding: utf-8 -*-
from openerp.osv import osv, fields
class MailComposeMessage(osv.TransientModel):
_inherit = 'mail.compose.message'
_columns = {
'private': fields.boolean('Send Internal Message'),
}

BIN
mail_private/static/description/check_recipients.png

After

Width: 751  |  Height: 352  |  Size: 73 KiB

BIN
mail_private/static/description/icon.png

After

Width: 100  |  Height: 100  |  Size: 2.1 KiB

67
mail_private/static/description/index.html

@ -0,0 +1,67 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Internal Messaging</h2>
<h3 class="oe_slogan">Send private messages to specified recipients, regardless of who are in followers list.</h3>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<blockquote>
The module will be available for Odoo 9.0 soon. You have time to buy Internal Messaging before price increase! (When you purchase 8.0 version, you get a right to download 9.0 and any further module versions).
</blockquote>
<p class="oe_mt32">
By default, to send a private message to specific recipient(s) you need to delete other followers included to the same document. The module allows to send private messages to recipients you specified, regardless of who are in the followers list.
</p>
<p>
It simplify internal communication in leads, when you need to send some private messages to your colleagues before reply to customer.
It helps in records like project tasks too. In a task with many participants, you can easily send message and only specified colleagues will be notified. It allows to have clean inbox for everybody. It's very essential, because people often neglect important message in Inbox full of useless messages.
</p>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h3 class="oe_slogan">How it works</h3>
<p class="oe_mt32">
Click on the "Send internal message" and choose the recipient(s). Then type any message and click on the "Send" button.
</p>
<div class="oe_demo oe_picture oe_screenshot">
<img src="check_recipients.png"/>
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<p class="oe_mt32">
As a result you can see the message with a dark background, which is sent to the corresponding recipient(s). Other followers of the document will not receive your message.
</p>
<div class="oe_demo oe_picture oe_screenshot">
<img src="result_message.png"/>
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2>Need our service?</h2>
<p class="oe_mt32">Contact us by <a href="mailto:it@it-projects.info">email</a> or fill out <a href="https://www.it-projects.info/page/website.contactus " target="_blank">request form</a></p>
<ul>
<li><a href="mailto:it@it-projects.info">it@it-projects.info <i class="fa fa-envelope-o"></i></a></li>
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li>
</ul>
</div>
</div>
</section>

BIN
mail_private/static/description/result_message.png

After

Width: 751  |  Height: 352  |  Size: 92 KiB

201
mail_private/static/src/js/mail_private.js

@ -0,0 +1,201 @@
openerp.mail_private = function(instance){
var mail = instance.mail;
instance.mail.ThreadComposeMessage.include({
init: function (parent, datasets, options) {
this._super.apply(this, arguments);
this.private = false;
},
bind_events: function(){
var self = this;
this.$('.oe_compose_post_private').on('click', self.on_toggle_quick_composer_private);
this._super.apply(this, arguments);
},
on_compose_fullmail: function (default_composition_mode) {
var self = this;
if(!this.do_check_attachment_upload()) {
return false;
}
var recipient_done = $.Deferred();
if (this.is_log) {
recipient_done.resolve([]);
}
else {
recipient_done = this.check_recipient_partners();
}
$.when(recipient_done).done(function (partner_ids) {
var context = {
'default_parent_id': self.id,
'default_body': mail.ChatterUtils.get_text2html(self.$el ? (self.$el.find('textarea:not(.oe_compact)').val() || '') : ''),
'default_attachment_ids': _.map(self.attachment_ids, function (file) {return file.id;}),
'default_partner_ids': partner_ids,
'default_is_log': self.is_log,
'default_private': self.private,
'mail_post_autofollow': true,
'mail_post_autofollow_partner_ids': partner_ids,
'is_private': self.is_private
};
if (default_composition_mode != 'reply' && self.context.default_model && self.context.default_res_id) {
context.default_model = self.context.default_model;
context.default_res_id = self.context.default_res_id;
}
var action = {
type: 'ir.actions.act_window',
res_model: 'mail.compose.message',
view_mode: 'form',
view_type: 'form',
views: [[false, 'form']],
target: 'new',
context: context,
};
self.do_action(action, {
'on_close': function(){ !self.parent_thread.options.view_inbox && self.parent_thread.message_fetch(); }
});
self.on_cancel();
});
},
do_send_message_post: function (partner_ids, log) {
var self = this;
var values = {
'body': this.$('textarea').val(),
'subject': false,
'parent_id': this.context.default_parent_id,
'attachment_ids': _.map(this.attachment_ids, function (file) {return file.id;}),
'partner_ids': partner_ids,
'context': _.extend(this.parent_thread.context, {
'mail_post_autofollow': true,
'mail_post_autofollow_partner_ids': partner_ids,
'default_private': self.private
}),
'type': 'comment',
'content_subtype': 'plaintext',
};
if (log || self.private) {
values.subtype = false;
}
else {
values.subtype = 'mail.mt_comment';
}
this.parent_thread.ds_thread._model.call('message_post', [this.context.default_res_id], values).done(function (message_id) {
var thread = self.parent_thread;
var root = thread == self.options.root_thread;
if (self.options.display_indented_thread < self.thread_level && thread.parent_message) {
var thread = thread.parent_message.parent_thread;
}
// create object and attach to the thread object
thread.message_fetch([["id", "=", message_id]], false, [message_id], function (arg, data) {
var message = thread.create_message_object( data.slice(-1)[0] );
// insert the message on dom
thread.insert_message( message, root ? undefined : self.$el, root );
});
self.on_cancel();
self.flag_post = false;
});
},
on_toggle_quick_composer: function (event) {
if (event.target.className == 'oe_compose_post') {
this.recipients = [];
this.private = false;
}
this._super.apply(this, arguments);
},
on_toggle_quick_composer_private: function (event) {
this.recipients = [];
var self = this;
var $input = $(event.target);
this.compute_emails_from();
var email_addresses = _.pluck(this.recipients, 'email_address');
var suggested_partners = $.Deferred();
// if clicked: call for suggested recipients
if (event.type == 'click') {
this.private = $input.hasClass('oe_compose_post_private');
this.is_log = false;
suggested_partners = this.parent_thread.get_recipients_for_internal_message([this.context.default_res_id], this.context)
.done(function (additional_recipients) {
var thread_recipients = additional_recipients[self.context.default_res_id];
_.each(thread_recipients, function (recipient) {
var parsed_email = mail.ChatterUtils.parse_email(recipient[1]);
if (_.indexOf(email_addresses, parsed_email[1]) == -1) {
self.recipients.push({
'checked': false,
'partner_id': recipient[0],
'full_name': recipient[1],
'name': parsed_email[0],
'email_address': parsed_email[1],
'reason': recipient[2],
});
}
});
});
}
else {
suggested_partners.resolve({});
}
// uncheck partners from compute_emails_from
_.each(this.recipients, function(r){
if (!r.partner_id){
r.checked = false;
}
});
// when call for suggested partners finished: re-render the widget
$.when(suggested_partners).pipe(function (additional_recipients) {
if ((!self.stay_open || (event && event.type == 'click')) && (!self.show_composer || !self.$('textarea:not(.oe_compact)').val().match(/\S+/) && !self.attachment_ids.length)) {
self.show_composer = !self.show_composer || self.stay_open;
self.reinit();
}
if (!self.stay_open && self.show_composer && (!event || event.type != 'blur')) {
self.$('textarea:not(.oe_compact):first').focus();
}
});
return suggested_partners;
}
});
instance.mail.Thread.include({
get_recipients_for_internal_message: function(ids, context){
var self = this;
self.result = {};
return new instance.web.Model(context.default_model).call(
'read', [ids, ['message_follower_ids', 'partner_id'], context]
).then(function (thread) {
for (var i = 0; i < thread.length; i++) {
var res_id = thread[i].id;
var recipient_ids = thread[i].message_follower_ids;
self.result[res_id] = [];
// Add customer
self.customer = thread[i].partner_id;
if (self.customer && !recipient_ids.includes(self.customer[0])) {
recipient_ids.splice(0, 0, self.customer[0]);
}
return new instance.web.Model('res.partner').call(
'read', [recipient_ids, ['name', 'email', 'user_ids']]
).then(function (res_partners){
for (var j = 0; j < res_partners.length; j++) {
var partner = res_partners[j];
if (!_.include(partner.user_ids, self.session.uid)){
var reason = 'Follower';
if (self.customer && partner.id == self.customer[0]){
reason = 'Partner';
}
self.result[res_id].push(
[partner.id, partner.name + '<' + partner.email + '>', reason]
);
}
}
return self.result;
});
}
return self.result;
});
}
});
};

21
mail_private/static/src/xml/mail_private.xml

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<template>
<t t-extend="mail.compose_message">
<t t-jquery="a[title='Send a message to all followers of the document']" t-operation="after">
<span class="oe_grey oe_sep_word">or</span><a class="oe_compose_post_private" t-if="!widget.options.compose_placeholder and !widget.options.view_mailbox" title="Send a message to specified recipients only">Send internal message</a>
</t>
</t>
<t t-extend="mail.thread.list_recipients">
<t t-jquery="[t-if='!widget.is_private']" t-operation="replace">
<t t-if="!widget.is_private and !widget.private">
<span class="oe_all_follower">
<t t-if="widget.parent_thread.parent_message.record_name">
Followers of <t t-raw="'&quot;' + widget.parent_thread.parent_message.record_name + '&quot;'"/>
</t>
<t t-if="!widget.parent_thread.parent_message.record_name and widget.options.view_inbox">My Followers</t>
<t t-if="!widget.parent_thread.parent_message.record_name and !widget.options.view_inbox">Followers of this document</t>
</span>
</t>
</t>
</t>
</template>

15
mail_private/template.xml

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template
id="assets_backend"
name="mail_private_assets_backend"
inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script
type="text/javascript"
src="/mail_private/static/src/js/mail_private.js"></script>
</xpath>
</template>
</data>
</openerp>

27
mail_private/view.xml

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="mail_private_email_compose_message_wizard_form" model="ir.ui.view">
<field name="name">mail.private.mail.compose.message.form</field>
<field name="model">mail.compose.message</field>
<field name="inherit_id" ref="mail.email_compose_message_wizard_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@groups='base.group_user']" position="replace">
<div groups="base.group_user" attrs="{'invisible': [('is_log', '=', True)]}">
<field name="private" invisible="1"/>
<!--<field name="private"/>-->
<span attrs="{'invisible': [('composition_mode', '!=', 'mass_mail')]}">
<strong>Email mass mailing</strong> on
<span attrs="{'invisible': [('use_active_domain', '=', True)]}">the selected records</span>
<span attrs="{'invisible': [('use_active_domain', '=', False)]}">the current search filter</span>.
</span>
<span attrs="{'invisible':['|', ('composition_mode', '!=', 'comment'), ('private', '=', True)]}">Followers of the document and</span>
<field name="partner_ids" widget="many2many_tags_email" placeholder="Add contacts to notify..."
context="{'force_email':True, 'show_email':True}"
attrs="{'invisible': [('composition_mode', '!=', 'comment')]}"/>
</div>
</xpath>
</field>
</record>
</data>
</openerp>

6
mail_recovery/README.rst

@ -18,7 +18,7 @@ Contributors
Sponsors Sponsors
-------- --------
* `IT-Projects LLC <https://it-projects.info>`__
* `IT-Projects LLC <https://it-projects.info>`___
Further information Further information
=================== ===================
@ -27,8 +27,8 @@ Demo: http://runbot.it-projects.info/demo/mail-addons/9.0
HTML Description: https://apps.odoo.com/apps/modules/9.0/mail_recovery/ HTML Description: https://apps.odoo.com/apps/modules/9.0/mail_recovery/
Usage instructions: `<doc/index.rst>`__
Usage instructions: `<doc/index.rst>`___
Changelog: `<doc/changelog.rst>`__
Changelog: `<doc/changelog.rst>`___
Tested on Odoo 9.0 fd9eb2e4819031c6758c021f4c335b591367632d Tested on Odoo 9.0 fd9eb2e4819031c6758c021f4c335b591367632d

4
mail_recovery/doc/changelog.rst

@ -1,5 +1,5 @@
Changelog
=========
Updates
=======
`1.0.0` `1.0.0`
------- -------

4
mail_sent/doc/changelog.rst

@ -1,7 +1,7 @@
.. _changelog: .. _changelog:
Changelog
=========
Updates
=======
`1.0.2` `1.0.2`
------- -------

1
mail_sent/models.py

@ -28,5 +28,6 @@ class MailMessage(models.Model):
class MailComposeMessage(models.TransientModel): class MailComposeMessage(models.TransientModel):
_inherit = 'mail.compose.message' _inherit = 'mail.compose.message'
sent = fields.Boolean('Sent', help='dummy field to fix inherit error') sent = fields.Boolean('Sent', help='dummy field to fix inherit error')

2
res_partner_mails_count/models.py

@ -3,7 +3,7 @@
from openerp import models, fields, api from openerp import models, fields, api
class res_partner(models.Model):
class ResPartner(models.Model):
_inherit = 'res.partner' _inherit = 'res.partner'
mails_to = fields.Integer(compute="_mails_to") mails_to = fields.Integer(compute="_mails_to")
mails_from = fields.Integer(compute="_mails_from") mails_from = fields.Integer(compute="_mails_from")

6
res_partner_strip_email/models.py

@ -4,18 +4,18 @@ from openerp import api
from openerp import models from openerp import models
class res_partner_strip_email(models.Model):
class ResPartnerStripEmail(models.Model):
_inherit = 'res.partner' _inherit = 'res.partner'
@api.one @api.one
def write(self, vals): def write(self, vals):
vals = self._check_email_field(vals) vals = self._check_email_field(vals)
return super(res_partner_strip_email, self).write(vals)
return super(ResPartnerStripEmail, self).write(vals)
@api.model @api.model
def create(self, vals): def create(self, vals):
vals = self._check_email_field(vals) vals = self._check_email_field(vals)
return super(res_partner_strip_email, self).create(vals)
return super(ResPartnerStripEmail, self).create(vals)
def _check_email_field(self, vals): def _check_email_field(self, vals):
if vals.get('email'): if vals.get('email'):

Loading…
Cancel
Save