[MERGE] from upstream

bzr revid: fva@openerp.com-20130108175216-qsvgflz81jur21vu
This commit is contained in:
Frédéric van der Essen
2013-01-08 18:52:16 +01:00
6 changed files with 145 additions and 99 deletions
+1 -1
View File
@@ -97,7 +97,7 @@
<form string="Account Period" version="7.0">
<header>
<button string="Close Period" name="%(account.action_account_period_close)d" type="action" class="oe_highlight" states="draft"/>
<button name="action_draft" states="done" string="Set to Draft" type="object" groups="account.group_account_manager"/>
<button name="action_draft" states="done" string="Re-Open Period" type="object" groups="account.group_account_manager"/>
<field name="state" widget="statusbar" nolabel="1"/>
</header>
<sheet>
+56 -21
View File
@@ -25,6 +25,7 @@ import dateutil
import email
import logging
import pytz
import re
import time
import xmlrpclib
from email.message import Message
@@ -647,14 +648,14 @@ class mail_thread(osv.AbstractModel):
"""
if context is None:
context = {}
data = {}
if isinstance(custom_values, dict):
data = custom_values.copy()
model = context.get('thread_model') or self._name
model_pool = self.pool.get(model)
fields = model_pool.fields_get(cr, uid, context=context)
data = model_pool.default_get(cr, uid, fields, context=context)
if 'name' in fields and not data.get('name'):
data['name'] = msg_dict.get('subject', '')
if custom_values and isinstance(custom_values, dict):
data.update(custom_values)
res_id = model_pool.create(cr, uid, data, context=context)
return res_id
@@ -819,6 +820,41 @@ class mail_thread(osv.AbstractModel):
"now deprecated res.log.")
self.message_post(cr, uid, [id], message, context=context)
def message_create_partners_from_emails(self, cr, uid, emails, context=None):
""" Convert a list of emails into a list partner_ids and a list
new_partner_ids. The return value is non conventional because
it is meant to be used by the mail widget.
:return dict: partner_ids and new_partner_ids
"""
partner_obj = self.pool.get('res.partner')
mail_message_obj = self.pool.get('mail.message')
partner_ids = []
new_partner_ids = []
for email in emails:
m = re.search(r"((.+?)\s*<)?([^<>]+@[^<>]+)>?", email, re.IGNORECASE | re.DOTALL)
name = m.group(2) or m.group(0)
email = m.group(3)
ids = partner_obj.search(cr, SUPERUSER_ID, [('email', '=', email)], context=context)
if ids:
partner_ids.append(ids[0])
else:
partner_id = partner_obj.create(cr, uid, {
'name': name or email,
'email': email,
}, context=context)
new_partner_ids.append(partner_id)
# link mail with this from mail to the new partner id
message_ids = mail_message_obj.search(cr, SUPERUSER_ID, ['|', ('email_from', '=', email), ('email_from', 'ilike', '<%s>' % email), ('author_id', '=', False)], context=context)
if message_ids:
mail_message_obj.write(cr, SUPERUSER_ID, message_ids, {'email_from': None, 'author_id': partner_id}, context=context)
return {
'partner_ids': partner_ids,
'new_partner_ids': new_partner_ids,
}
def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification',
subtype=None, parent_id=False, attachments=None, context=None, **kwargs):
""" Post a new message in an existing thread, returning the new
@@ -907,7 +943,7 @@ class mail_thread(osv.AbstractModel):
return mail_message.create(cr, uid, values, context=context)
def message_post_user_api(self, cr, uid, thread_id, body='', parent_id=False,
attachment_ids=None, extra_emails=None, content_subtype='plaintext',
attachment_ids=None, content_subtype='plaintext',
context=None, **kwargs):
""" Wrapper on message_post, used for user input :
- mail gateway
@@ -920,26 +956,12 @@ class mail_thread(osv.AbstractModel):
- type and subtype: comment and mail.mt_comment by default
- attachment_ids: supposed not attached to any document; attach them
to the related document. Should only be set by Chatter.
- extra_email: [ 'Fabien <fpi@openerp.com>', 'al@openerp.com' ]
"""
partner_obj = self.pool.get('res.partner')
mail_message_obj = self.pool.get('mail.message')
ir_attachment = self.pool.get('ir.attachment')
extra_emails = extra_emails or []
# 1.A.1: pre-process partners and incoming extra_emails
# 1.A.1: add recipients of parent message
partner_ids = set([])
for email in extra_emails:
partner_id = partner_obj.find_or_create(cr, uid, email, context=context)
# link mail with this from mail to the new partner id
partner_msg_ids = mail_message_obj.search(cr, SUPERUSER_ID, [('email_from', '=', email), ('author_id', '=', False)], context=context)
if partner_id and partner_msg_ids:
mail_message_obj.write(cr, SUPERUSER_ID, partner_msg_ids, {'email_from': None, 'author_id': partner_id}, context=context)
partner_ids.add((4, partner_id))
if partner_ids:
self.message_subscribe(cr, uid, [thread_id], [item[1] for item in partner_ids], context=context)
# 1.A.2: add recipients of parent message
if parent_id:
parent_message = mail_message_obj.browse(cr, uid, parent_id, context=context)
partner_ids |= set([(4, partner.id) for partner in parent_message.partner_ids])
@@ -947,8 +969,21 @@ class mail_thread(osv.AbstractModel):
if self._name == 'mail.thread' and parent_message.author_id.id:
partner_ids.add((4, parent_message.author_id.id))
# 1.A.3: add specified recipients
partner_ids |= set(kwargs.pop('partner_ids', []))
# 1.A.2: add specified recipients
param_partner_ids = set()
for item in kwargs.pop('partner_ids', []):
if isinstance(item, (list)):
param_partner_ids.add((item[0], item[1]))
elif isinstance(item, (int, long)):
param_partner_ids.add((4, item))
else:
param_partner_ids.add(item)
partner_ids |= param_partner_ids
# 1.A.3: add parameters recipients as follower
# TDE FIXME in 7.1: should check whether this comes from email_list or partner_ids
if param_partner_ids and self._name != 'mail.thread':
self.message_subscribe(cr, uid, [thread_id], [pid[1] for pid in param_partner_ids], context=context)
# 1.B: handle body, message_type and message_subtype
if content_subtype == 'plaintext':
+80 -73
View File
@@ -253,7 +253,14 @@ openerp.mail = function (session) {
} else {
this.avatar = mail.ChatterUtils.get_image(this.session, 'res.users', 'image_small', this.session.uid);
}
if (this.author_id) {
var email = this.author_id[1].match(/(.*)<(.*@.*)>/);
if (!email) {
this.author_id.push(_.str.escapeHTML(this.author_id[1]), '', this.author_id[1]);
} else {
this.author_id.push(_.str.escapeHTML(email[0]), _.str.trim(email[1]), email[2]);
}
}
},
@@ -370,6 +377,7 @@ openerp.mail = function (session) {
this.show_compact_message = false;
this.show_delete_attachment = true;
this.emails_from = [];
this.partners_from = [];
},
start: function () {
@@ -494,43 +502,43 @@ openerp.mail = function (session) {
this.$(".oe_msg_attachment_list").on('click', '.oe_delete', this.on_attachment_delete);
this.$(".oe_emails_from").on('change', 'input', this.on_checked_email_from);
this.$(".oe_partners_from").on('change', 'input', this.on_checked_partner_from);
},
on_compose_fullmail: function (default_composition_mode) {
var self = this;
if(!this.do_check_attachment_upload()) {
return false;
}
if (default_composition_mode == 'reply') {
// create list of new partners
this.check_recipient_partners().done(function (partner_ids) {
var context = {
'default_composition_mode': default_composition_mode,
'default_parent_id': this.id,
'default_body': mail.ChatterUtils.get_text2html(this.$el ? (this.$el.find('textarea:not(.oe_compact)').val() || '') : ''),
'default_attachment_ids': this.attachment_ids,
'default_parent_id': self.id,
'default_body': mail.ChatterUtils.get_text2html(self.$el ? (self.$el.find('textarea:not(.oe_compact)').val() || '') : ''),
'default_attachment_ids': self.attachment_ids,
'default_partner_ids': partner_ids,
};
} else {
var context = {
'default_model': this.context.default_model,
'default_res_id': this.context.default_res_id,
'default_composition_mode': default_composition_mode,
'default_parent_id': this.id,
'default_body': mail.ChatterUtils.get_text2html(this.$el ? (this.$el.find('textarea:not(.oe_compact)').val() || '') : ''),
'default_attachment_ids': this.attachment_ids,
};
}
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,
};
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);
self.on_cancel();
});
this.do_action(action);
this.on_cancel();
},
reinit: function() {
@@ -562,63 +570,65 @@ openerp.mail = function (session) {
}
},
check_recipient_partners: function (emails) {
check_recipient_partners: function () {
var self = this;
var deferreds = [];
for (var i = 0; i < emails.length; i++) {
deferreds.push($.Deferred());
}
var ds_partner = new session.web.DataSetSearch(this, 'res.partner');
_.each(emails, function (email) {
ds_partner.call('search', [[['email', 'ilike', email]]]).then(function (partner_ids) {
var deferred = deferreds[_.indexOf(emails, email)];
if (!partner_ids.length) {
var pop = new session.web.form.FormOpenPopup(this);
pop.show_element(
'res.partner',
0,
{
'default_email': email,
'force_email': true,
'ref': "compound_context",
},
{
title: _t("Please complete partner's informations"),
}
);
pop.on('write_completed, closed', self, function () {
deferred.resolve();
});
}
else {
var partners_from = [];
var emails = [];
_.each(this.emails_from, function (email_from) {
if (email_from[1] && !_.find(emails, function (email) {return email == email_from[0][4];})) {
emails.push(email_from[0][1]);
}
});
var deferred_check = $.Deferred();
self.parent_thread.ds_thread._model.call('message_create_partners_from_emails', [emails]).then(function (partners) {
partners_from = _.clone(partners.partner_ids);
var deferreds = [];
_.each(partners.new_partner_ids, function (id) {
var deferred = $.Deferred()
deferreds.push(deferred);
var pop = new session.web.form.FormOpenPopup(this);
pop.show_element(
'res.partner',
id,
{
'force_email': true,
'ref': "compound_context",
},
{
title: _t("Please complete partner's informations"),
}
);
pop.on('closed', self, function () {
deferred.resolve();
}
return deferred;
});
partners_from.push(id);
});
$.when.apply( $, deferreds ).then(function () {
deferred_check.resolve(partners_from);
});
});
return $.when.apply( $, deferreds ).done();
return deferred_check;
},
on_message_post: function (event) {
var self = this;
if (this.do_check_attachment_upload() && (this.attachment_ids.length || this.$('textarea').val().match(/\S+/))) {
// create list of new partners
var extra_email = _.map(_.filter(this.emails_from, function (f) {return f[1]}), function (f) {return f[0]});
this.check_recipient_partners(extra_email).done(function () {
self.do_send_message_post();
this.check_recipient_partners().done(function (partner_ids) {
self.do_send_message_post(partner_ids);
});
}
},
/*do post a message and fetch the message*/
do_send_message_post: function () {
do_send_message_post: function (partner_ids) {
var self = this;
this.parent_thread.ds_thread._model.call('message_post_user_api', [this.context.default_res_id], {
'body': this.$('textarea').val(),
'subject': false,
'parent_id': this.context.default_parent_id,
'attachment_ids': _.map(this.attachment_ids, function (file) {return file.id;}),
'extra_emails': _.map(_.filter(this.emails_from, function (f) {return f[1]}), function (f) {return f[0]}),
'partner_ids': partner_ids,
'context': this.parent_thread.context,
}).done(function (message_id) {
var thread = self.parent_thread;
@@ -678,26 +688,24 @@ openerp.mail = function (session) {
_.each(this.options.root_thread.messages, function (msg) {messages.push(msg); messages.concat(msg.get_childs());});
}
var emails_from = _.map(_.filter(messages,
function (thread) {return thread.author_id && !thread.author_id[0];}),
function (thread) {return thread.author_id[1];});
return _.each(emails_from, function (email_from) {
if (!_.find(self.emails_from, function (from) {return from[0] == email_from;})) {
self.emails_from.push([email_from, true]);
_.each(messages, function (thread) {
if (thread.author_id && !thread.author_id[0] &&
!_.find(self.emails_from, function (from) {return from[0][4] == thread.author_id[4];})) {
self.emails_from.push([thread.author_id, true]);
}
});
return self.emails_from;
},
on_checked_email_from: function (event) {
var $input = $(event.target);
var email = $input.attr("data");
_.each(this.emails_from, function (email_from) {
if (email_from[0] == email) {
if (email_from[0][4] == email) {
email_from[1] = $input.is(":checked");
}
});
}
},
});
/**
@@ -1690,7 +1698,6 @@ openerp.mail = function (session) {
this.defaults[key.replace(/^search_default_/, '')] = this.context[key];
}
}
this.action.params = _.extend({
'display_indented_thread': 1,
'show_reply_button': true,
@@ -221,11 +221,14 @@ openerp_mail_followers = function(session, mail) {
var nb_subtype = 0;
_(records).each(function (record) {nb_subtype++;});
if (nb_subtype > 1) {
this.$('hr').show();
_(records).each(function (record, record_name) {
record.name = record_name;
record.followed = record.followed || undefined;
$(session.web.qweb.render('mail.followers.subtype', {'record': record})).appendTo( self.$('.oe_subtype_list') );
});
} else {
this.$('hr').hide();
}
},
+4 -4
View File
@@ -132,8 +132,8 @@
<div class="oe_emails_from">
<t t-foreach='widget.emails_from' t-as='email_from'>
<label title="Add them into recipients and followers">
<input type="checkbox" t-att-checked="email_from[1] ? 'checked' : undefind" t-att-data="email_from[0]"/>
<t t-raw="email_from[0]"/>
<input type="checkbox" t-att-checked="email_from[1] ? 'checked' : undefind" t-att-data="email_from[0][4]"/>
<t t-raw="email_from[0][2]"/>
</label>
</t>
</div>
@@ -243,8 +243,8 @@
<t t-if="widget.attachment_ids.length > 0">
<div class="oe_msg_attachment_list"></div>
</t>
<a t-if="widget.author_id and widget.options.show_link and widget.author_id[0]" t-attf-href="#model=res.partner&amp;id=#{widget.author_id[0]}"><t t-raw="widget.author_id[1]"/></a>
<span t-if="widget.author_id and (!widget.options.show_link or !widget.author_id[0])"><t t-raw="widget.author_id[1]"/></span>
<a t-if="widget.author_id and widget.options.show_link and widget.author_id[0]" t-attf-href="#model=res.partner&amp;id=#{widget.author_id[0]}"><t t-raw="widget.author_id[2]"/></a>
<span t-if="widget.author_id and (!widget.options.show_link or !widget.author_id[0])"><t t-raw="widget.author_id[2]"/></span>
<span class='oe_subtle'>•</span>
<span t-att-title="widget.date"><t t-raw="widget.timerelative"/></span>
<span t-if="!widget.options.readonly" class='oe_subtle'>•</span>
@@ -168,6 +168,7 @@ class mail_compose_message(osv.TransientModel):
reply_subject = "%s %s" % (re_prefix, reply_subject)
# get partner_ids from original message
partner_ids = [partner.id for partner in message_data.partner_ids] if message_data.partner_ids else []
partner_ids += context.get('default_partner_ids', [])
# update the result
result = {