Thibault Delavallée (OpenERP) has proposed merging
lp:~openerp-dev/openobject-addons/trunk-mail-concreting-tde into
lp:~openerp-dev/openobject-addons/trunk-openchatter-DOM-chm.
Requested reviews:
OpenERP R&D Team (openerp-dev)
For more details, see:
https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-mail-concreting-tde/+merge/131865
Misc server-side changes and fixes.
--
https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-mail-concreting-tde/+merge/131865
Your team OpenERP R&D Team is requested to review the proposed merge of
lp:~openerp-dev/openobject-addons/trunk-mail-concreting-tde into
lp:~openerp-dev/openobject-addons/trunk-openchatter-DOM-chm.
=== modified file 'account_voucher/voucher_sales_purchase_view.xml'
=== modified file 'analytic/analytic_view.xml'
=== modified file 'base_calendar/crm_meeting_view.xml'
=== modified file 'mail/mail_followers.py'
--- mail/mail_followers.py 2012-10-29 11:21:17 +0000
+++ mail/mail_followers.py 2012-10-29 11:30:38 +0000
@@ -84,11 +84,16 @@
return False
def set_message_read(self, cr, uid, msg_ids, read=None, context=None):
+<<<<<<< TREE
""" Set a message and its child messages as (un)read for uid.
:param bool read: read / unread
"""
# TDE note: use child_of or front-end send correct values ?
+=======
+ """ TDE note: add a comment, verify method calls, because js seems obfuscated. """
+ # TDE note: child_of to set unread ?
+>>>>>>> MERGE-SOURCE
user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
notif_ids = self.search(cr, uid, [
('partner_id', '=', user_pid),
=== modified file 'mail/mail_message.py'
--- mail/mail_message.py 2012-10-29 11:21:17 +0000
+++ mail/mail_message.py 2012-10-29 11:30:38 +0000
@@ -63,9 +63,14 @@
return name[:self._message_record_name_length] + '...'
def _get_record_name(self, cr, uid, ids, name, arg, context=None):
+<<<<<<< TREE
""" Return the related document name, using name_get. It is done using
SUPERUSER_ID, to be sure to have the record name correctly stored. """
# TDE note: regroup by model/ids, to have less queries to perform
+=======
+ """ Return the related document name, using name_get. It is done using
+ SUPERUSER_ID, to be sure to have the record name correctly stored. """
+>>>>>>> MERGE-SOURCE
result = dict.fromkeys(ids, False)
for message in self.read(cr, uid, ids, ['model', 'res_id'], context=context):
if not message.get('model') or not message.get('res_id'):
@@ -118,6 +123,7 @@
], 'Type',
help="Message type: email for email message, notification for system "\
"message, comment for other messages such as user replies"),
+<<<<<<< TREE
'email_from': fields.char('From',
help="Email address of the sender. This field is set when no matching partner is found for incoming emails."),
'author_id': fields.many2one('res.partner', 'Author',
@@ -125,6 +131,15 @@
'partner_ids': fields.many2many('res.partner', string='Recipients'),
'notified_partner_ids': fields.many2many('res.partner', 'mail_notification',
'message_id', 'partner_id', 'Recipients'),
+=======
+ 'email_from': fields.char('From',
+ help="Email address of the sender, to use if it does not match any partner."),
+ 'author_id': fields.many2one('res.partner', 'Author',
+ help="Partner that did write the message. If not set, try to use the From field instead."),
+ 'partner_ids': fields.many2many('res.partner', string='Recipients'),
+ 'notified_partner_ids': fields.many2many('res.partner', 'mail_notification',
+ 'message_id', 'partner_id', 'Recipients'),
+>>>>>>> MERGE-SOURCE
'attachment_ids': fields.many2many('ir.attachment', 'message_attachment_rel',
'message_id', 'attachment_id', 'Attachments'),
'parent_id': fields.many2one('mail.message', 'Parent Message', select=True, ondelete='set null', help="Initial thread message."),
@@ -206,6 +221,7 @@
:param dict message: read result of a mail.message
"""
+<<<<<<< TREE
# TDE note: this method should be optimized, to lessen the number of queries, will be done ASAP
is_author = False
if message['author_id']:
@@ -214,6 +230,15 @@
elif message['email_from']:
author_id = (0, message['email_from'])
+=======
+ is_author = False
+ if message['author_id']:
+ is_author = message['author_id'][0] == self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=None)['partner_id'][0]
+ author_id = message['author_id']
+ elif message['email_from']:
+ author_id = (0, message['email_from'])
+
+>>>>>>> MERGE-SOURCE
has_voted = False
if uid in message.get('vote_user_ids'):
has_voted = True
@@ -322,10 +347,18 @@
('id', 'child_of', message['id']),
('id', 'not in', message_loaded_ids),
], context=context, limit=self._message_read_more_limit)
- if not not_loaded_ids:
- continue
-
- # all_not_loaded_ids += not_loaded_ids
+<<<<<<< TREE
+ if not not_loaded_ids:
+ continue
+
+ # all_not_loaded_ids += not_loaded_ids
+=======
+ if not not_loaded_ids:
+ continue
+ # print 'not_loaded_ids', not_loaded_ids
+
+ # all_not_loaded_ids += not_loaded_ids
+>>>>>>> MERGE-SOURCE
# group childs not read
id_min, id_max, nb = max(not_loaded_ids), 0, 0
for not_loaded_id in not_loaded_ids:
@@ -388,12 +421,20 @@
ancestors and expandables
:return list: list of message structure for the Chatter widget
"""
+<<<<<<< TREE
# print 'message_read', ids, domain, message_unload_ids, thread_level, context, parent_id, limit
assert thread_level in [0, 1], 'message_read() thread_level should be 0 (flat) or 1 (1 level of thread); given %s.' % thread_level
domain = domain if domain is not None else []
message_unload_ids = message_unload_ids if message_unload_ids is not None else []
if message_unload_ids:
domain += [('id', 'not in', message_unload_ids)]
+=======
+ assert thread_level in [0, 1], 'message_read() thread_level should be 0 (flat) or 1 (1 level of thread); given %s.' % thread_level
+ domain = domain if domain is not None else []
+ message_unload_ids = message_unload_ids if message_unload_ids is not None else []
+ if message_unload_ids:
+ domain += [('id', 'not in', message_unload_ids)]
+>>>>>>> MERGE-SOURCE
limit = limit or self._message_read_limit
read_messages = {}
message_list = []
@@ -448,6 +489,7 @@
if not cr.fetchone():
cr.execute("""CREATE INDEX mail_message_model_res_id_idx ON mail_message (model, res_id)""")
+<<<<<<< TREE
def _search(self, cr, uid, args, offset=0, limit=None, order=None,
context=None, count=False, access_rights_uid=None):
""" Override that adds specific access rights of mail.message, to remove
@@ -500,6 +542,59 @@
else:
return list(final_ids)
+=======
+ def _search(self, cr, uid, args, offset=0, limit=None, order=None,
+ context=None, count=False, access_rights_uid=None):
+ """ Override that adds specific access rights of mail.message, to remove
+ ids uid could not see according to our custom rules. Please refer
+ to check_access_rule for more details about those rules.
+
+ After having received ids of a classic search, keep only:
+ - if author_id == pid, uid is the author, OR
+ - a notification (id, pid) exists, uid has been notified, OR
+ - uid have read access to the related document is model, res_id
+ - otherwise: remove the id
+ """
+ # Rules do not apply to administrator
+ if uid == SUPERUSER_ID:
+ return super(mail_message, self)._search(cr, uid, args, offset=offset, limit=limit, order=order,
+ context=context, count=count, access_rights_uid=access_rights_uid)
+ # Perform a super with count as False, to have the ids, not a counter
+ ids = super(mail_message, self)._search(cr, uid, args, offset=offset, limit=limit, order=order,
+ context=context, count=False, access_rights_uid=access_rights_uid)
+ if not ids and count:
+ return 0
+ elif not ids:
+ return ids
+
+ pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'])['partner_id'][0]
+ author_ids, partner_ids, allowed_ids = set([]), set([]), set([])
+ model_ids = {}
+
+ messages = super(mail_message, self).read(cr, uid, ids, ['author_id', 'model', 'res_id', 'notified_partner_ids'], context=context)
+ for message in messages:
+ if message.get('author_id') and message.get('author_id')[0] == pid:
+ author_ids.add(message.get('id'))
+ elif pid in message.get('notified_partner_ids'):
+ partner_ids.add(message.get('id'))
+ elif message.get('model') and message.get('res_id'):
+ model_ids.setdefault(message.get('model'), {}).setdefault(message.get('res_id'), set()).add(message.get('id'))
+
+ model_access_obj = self.pool.get('ir.model.access')
+ for doc_model, doc_dict in model_ids.iteritems():
+ if not model_access_obj.check(cr, uid, doc_model, 'read', False):
+ continue
+ doc_ids = doc_dict.keys()
+ allowed_doc_ids = self.pool.get(doc_model).search(cr, uid, [('id', 'in', doc_ids)], context=context)
+ allowed_ids |= set([message_id for allowed_doc_id in allowed_doc_ids for message_id in doc_dict[allowed_doc_id]])
+
+ final_ids = author_ids | partner_ids | allowed_ids
+ if count:
+ return len(final_ids)
+ else:
+ return list(final_ids)
+
+>>>>>>> MERGE-SOURCE
def check_access_rule(self, cr, uid, ids, operation, context=None):
""" Access rules of mail.message:
- read: if
@@ -623,6 +718,7 @@
self.pool.get('ir.attachment').unlink(cr, uid, attachments_to_delete, context=context)
return super(mail_message, self).unlink(cr, uid, ids, context=context)
+<<<<<<< TREE
def copy(self, cr, uid, id, default=None, context=None):
""" Overridden to avoid duplicating fields that are unique to each email """
if default is None:
@@ -712,6 +808,95 @@
"""
message = self.read(cr, uid, newid, ['model', 'res_id', 'author_id', 'subtype_id', 'partner_ids'], context=context)
+=======
+ def copy(self, cr, uid, id, default=None, context=None):
+ """ Overridden to avoid duplicating fields that are unique to each email """
+ if default is None:
+ default = {}
+ default.update(message_id=False, headers=False)
+ return super(mail_message, self).copy(cr, uid, id, default=default, context=context)
+
+ #------------------------------------------------------
+ # Messaging API
+ #------------------------------------------------------
+
+ MAIL_TEMPLATE = """<div>
+ % if message:
+ ${display_message(message)}
+ % endif
+ % for ctx_msg in context_messages:
+ ${display_message(ctx_msg)}
+ % endfor
+ % if add_expandable:
+ ${display_expandable()}
+ % endif
+ ${display_message(header_message)}
+ </div>
+
+ <%def name="display_message(message)">
+ <div>
+ Subject: ${message.subject}<br />
+ Body: ${message.body}
+ </div>
+ </%def>
+
+ <%def name="display_expandable()">
+ <div>This is an expandable.</div>
+ </%def>
+ """
+
+ def message_quote_context(self, cr, uid, id, context=None, limit=3, add_original=False):
+ """
+ 1. message.parent_id = False: new thread, no quote_context
+ 2. get the lasts messages in the thread before message
+ 3. get the message header
+ 4. add an expandable between them
+
+ :param dict quote_context: options for quoting
+ :return string: html quote
+ """
+ add_expandable = False
+
+ message = self.browse(cr, uid, id, context=context)
+ if not message.parent_id:
+ return ''
+ context_ids = self.search(cr, uid, [
+ ('parent_id', '=', message.parent_id.id),
+ ('id', '<', message.id),
+ ], limit=limit, context=context)
+
+ if len(context_ids) >= limit:
+ add_expandable = True
+ context_ids = context_ids[0:-1]
+
+ context_ids.append(message.parent_id.id)
+ context_messages = self.browse(cr, uid, context_ids, context=context)
+ header_message = context_messages.pop()
+
+ try:
+ if not add_original:
+ message = False
+ result = MakoTemplate(self.MAIL_TEMPLATE).render_unicode(message=message,
+ context_messages=context_messages,
+ header_message=header_message,
+ add_expandable=add_expandable,
+ # context kw would clash with mako internals
+ ctx=context,
+ format_exceptions=True)
+ result = result.strip()
+ return result
+ except Exception:
+ _logger.exception("failed to render mako template for quoting message")
+ return ''
+ return result
+
+ def _notify(self, cr, uid, newid, context=None):
+ """ Add the related record followers to the destination partner_ids if is not a private message.
+ Call mail_notification.notify to manage the email sending
+ """
+ message = self.read(cr, uid, newid, ['model', 'res_id', 'author_id', 'subtype_id', 'partner_ids'], context=context)
+
+>>>>>>> MERGE-SOURCE
partners_to_notify = set([])
# message has no subtype_id: pure log message -> no partners, no one notified
if not message.get('subtype_id'):
=== modified file 'mail/mail_message_view.xml'
=== modified file 'mail/mail_thread.py'
--- mail/mail_thread.py 2012-10-29 10:12:30 +0000
+++ mail/mail_thread.py 2012-10-29 11:30:38 +0000
@@ -707,6 +707,7 @@
return mail_message.create(cr, uid, values, context=context)
+<<<<<<< TREE
def message_post_api(self, cr, uid, thread_id, body='', subject=False, parent_id=False, attachment_ids=None, context=None):
""" Wrapper on message_post, used only in Chatter (JS). The purpose is
to handle attachments.
@@ -717,14 +718,37 @@
# HACK FIXME: Chatter: attachments linked to the document (not done JS-side), load the message
if attachment_ids:
+=======
+ def message_post_api(self, cr, uid, thread_id, body='', subject=False, type='notification',
+ parent_id=False, attachment_ids=None, context=None):
+ """ Wrapper on message_post, used only in Chatter (JS). The purpose is
+ to handle attachments.
+
+ # TDE FIXME: body is plaintext: convert it into html
+ """
+ new_message_id = self.message_post(cr, uid, thread_id=thread_id, body=body, subject=subject, type=type,
+ subtype='mail.mt_comment', parent_id=parent_id, context=context)
+
+ # HACK FIXME: Chatter: attachments linked to the document (not done JS-side), load the message
+ if attachment_ids:
+>>>>>>> MERGE-SOURCE
ir_attachment = self.pool.get('ir.attachment')
mail_message = self.pool.get('mail.message')
+<<<<<<< TREE
filtered_attachment_ids = ir_attachment.search(cr, SUPERUSER_ID, [
('res_model', '=', 'mail.compose.message'),
('res_id', '=', 0),
('create_uid', '=', uid),
('id', 'in', attachment_ids)], context=context)
if filtered_attachment_ids:
+=======
+ filtered_attachment_ids = ir_attachment.search(cr, SUPERUSER_ID, [
+ ('res_model', '=', 'mail.message'),
+ ('res_id', '=', 0),
+ ('create_uid', '=', uid),
+ ('id', 'in', attachment_ids)], context=context)
+ if filtered_attachment_ids:
+>>>>>>> MERGE-SOURCE
ir_attachment.write(cr, SUPERUSER_ID, attachment_ids, {'res_model': self._name, 'res_id': thread_id}, context=context)
mail_message.write(cr, SUPERUSER_ID, [new_message_id], {'attachment_ids': [(6, 0, [pid for pid in attachment_ids])]}, context=context)
=== modified file 'mail/static/src/js/mail.js'
--- mail/static/src/js/mail.js 2012-10-29 11:22:54 +0000
+++ mail/static/src/js/mail.js 2012-10-29 11:30:38 +0000
@@ -353,9 +353,14 @@
this.context.default_res_id,
mail.ChatterUtils.get_text2html(body),
false,
+<<<<<<< TREE
+=======
+ 'comment',
+>>>>>>> MERGE-SOURCE
this.context.default_parent_id,
attachments,
this.parent_thread.context
+<<<<<<< TREE
]).then(function (record) {
var thread = self.parent_thread;
// create object and attach to the thread object
@@ -371,6 +376,13 @@
}
});
//session.web.unblockUI();
+=======
+ ]).then(function(records){
+ // TDE note: temp deactivation, because this will be fixed in DOM-CHM
+ // self.parent_thread.switch_new_message(records);
+ // self.datasets.attachment_ids=[];
+ // self.on_cancel();
+>>>>>>> MERGE-SOURCE
});
return true;
}
@@ -1102,6 +1114,7 @@
// domain and context: options + additional
fetch_domain = replace_domain ? replace_domain : this.domain;
fetch_context = replace_context ? replace_context : this.context;
+<<<<<<< TREE
var message_loaded_ids = this.id ? [this.id].concat( self.get_child_ids() ) : self.get_child_ids();
// CHM note : option for sending in flat mode by server
@@ -1109,6 +1122,12 @@
return this.ds_message.call('message_read', [ids, fetch_domain, message_loaded_ids, nb_indented_thread, fetch_context, this.context.default_parent_id || undefined])
.then(callback ? _.bind(callback, this, arguments) : this.proxy('switch_new_message'));
+=======
+ var message_loaded = [this.datasets.id||0].concat( self.options.thread._parents[0].get_child_ids() );
+
+ return this.ds_message.call('message_read', [ids, fetch_domain, message_loaded, 1, fetch_context, this.context.default_parent_id || undefined]
+ ).then(this.proxy('switch_new_message'));
+>>>>>>> MERGE-SOURCE
},
/**
=== modified file 'mail/tests/test_mail.py'
=== modified file 'project/project_view.xml'
=== modified file 'project_issue/project_issue_view.xml'
=== modified file 'sale/sale_view.xml'
_______________________________________________
Mailing list: https://launchpad.net/~openerp-dev-gtk
Post to : [email protected]
Unsubscribe : https://launchpad.net/~openerp-dev-gtk
More help : https://help.launchpad.net/ListHelp