[MERGE] with trunk

bzr revid: api@openerp.com-20121211153352-l1ikpqgz8cxmuuu0
This commit is contained in:
Arnaud Pineux 2012-12-11 16:33:52 +01:00
commit d288b45bb3
10 changed files with 108 additions and 30 deletions

View File

@ -166,7 +166,7 @@ class account_analytic_account(osv.osv):
_columns = {
'name': fields.char('Account/Contract Name', size=128, required=True),
'complete_name': fields.function(_get_full_name, type='char', string='Full Account Name'),
'code': fields.char('Reference', size=24, select=True),
'code': fields.char('Reference', select=True),
'type': fields.selection([('view','Analytic View'), ('normal','Analytic Account'),('contract','Contract or Project'),('template','Template of Contract')], 'Type of Account', required=True,
help="If you select the View Type, it means you won\'t allow to create journal entries using that account.\n"\
"The type 'Analytic account' stands for usual accounts that you only want to use in accounting.\n"\

View File

@ -35,5 +35,6 @@ import wizard
import res_config
import mail_group_menu
import update
import controllers
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,3 @@
import main
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,22 @@
import base64
import openerp.addons.web.http as oeweb
from openerp.addons.web.controllers.main import content_disposition
#----------------------------------------------------------
# Controller
#----------------------------------------------------------
class MailController(oeweb.Controller):
_cp_path = '/mail'
@oeweb.httprequest
def download_attachment(self, req, model, id, method, attachment_id, **kw):
Model = req.session.model(model)
res = getattr(Model, method)(int(id), int(attachment_id))
if res:
filecontent = base64.b64decode(res.get('base64'))
filename = res.get('filename')
if filecontent and filename:
return req.make_response(filecontent,
headers=[('Content-Type', 'application/octet-stream'),
('Content-Disposition', content_disposition(filename, req))])
return req.not_found()

View File

@ -204,6 +204,22 @@ class mail_message(osv.Model):
self.write(cr, SUPERUSER_ID, message.get('id'), {'vote_user_ids': [(3, uid)]}, context=context)
return new_has_voted or False
#------------------------------------------------------
# download an attachment
#------------------------------------------------------
def download_attachment(self, cr, uid, id_message, attachment_id, context=None):
""" Return the content of linked attachments. """
message = self.browse(cr, uid, id_message, context=context)
if attachment_id in [attachment.id for attachment in message.attachment_ids]:
attachment = self.pool.get('ir.attachment').browse(cr, SUPERUSER_ID, attachment_id, context=context)
if attachment.datas and attachment.datas_fname:
return {
'base64': attachment.datas,
'filename': attachment.datas_fname,
}
return False
#------------------------------------------------------
# Notification API
#------------------------------------------------------
@ -294,7 +310,7 @@ class mail_message(osv.Model):
partner_tree = dict((partner[0], partner) for partner in partners)
# 2. Attachments
attachments = ir_attachment_obj.read(cr, uid, list(attachment_ids), ['id', 'datas_fname'], context=context)
attachments = ir_attachment_obj.read(cr, SUPERUSER_ID, list(attachment_ids), ['id', 'datas_fname'], context=context)
attachments_tree = dict((attachment['id'], {'id': attachment['id'], 'filename': attachment['datas_fname']}) for attachment in attachments)
# 3. Update message dictionaries

View File

@ -29,8 +29,13 @@ openerp.mail = function (session) {
},
/* Get the url of an attachment {'id': id} */
get_attachment_url: function (session, attachment) {
return session.url('/web/binary/saveas', {model: 'ir.attachment', field: 'datas', filename_field: 'datas_fname', id: attachment['id']});
get_attachment_url: function (session, message_id, attachment_id) {
return session.url('/mail/download_attachment', {
'model': 'mail.message',
'id': message_id,
'method': 'download_attachment',
'attachment_id': attachment_id
});
},
/**
@ -258,7 +263,7 @@ openerp.mail = function (session) {
for (var l in this.attachment_ids) {
var attach = this.attachment_ids[l];
if (!attach.formating) {
attach.url = mail.ChatterUtils.get_attachment_url(this.session, attach);
attach.url = mail.ChatterUtils.get_attachment_url(this.session, this.id, attach.id);
attach.filetype = mail.ChatterUtils.filetype(attach.filename);
attach.name = mail.ChatterUtils.breakword(attach.name || attach.filename);
attach.formating = true;
@ -420,18 +425,23 @@ openerp.mail = function (session) {
/* when the file is uploaded
*/
on_attachment_loaded: function (event, result) {
for (var i in this.attachment_ids) {
if (this.attachment_ids[i].filename == result.filename && this.attachment_ids[i].upload) {
this.attachment_ids[i]={
'id': result.id,
'name': result.name,
'filename': result.filename,
'url': mail.ChatterUtils.get_attachment_url(this.session, result)
};
if (result.erorr || !result.id ) {
this.do_warn( session.web.qweb.render('mail.error_upload'), result.error);
this.attachment_ids = _.filter(this.attachment_ids, function (val) { return !val.upload; });
} else {
for (var i in this.attachment_ids) {
if (this.attachment_ids[i].filename == result.filename && this.attachment_ids[i].upload) {
this.attachment_ids[i]={
'id': result.id,
'name': result.name,
'filename': result.filename,
'url': mail.ChatterUtils.get_attachment_url(this.session, this.id, result.id)
};
}
}
}
this.display_attachments();
var $input = this.$('input.oe_form_binary_file');
$input.after($input.clone(true)).remove();
this.$(".oe_attachment_file").show();
@ -484,6 +494,11 @@ openerp.mail = function (session) {
},
on_compose_fullmail: function (default_composition_mode) {
if(!this.do_check_attachment_upload()) {
return false;
}
if (default_composition_mode == 'reply') {
var context = {
'default_composition_mode': default_composition_mode,
@ -534,31 +549,31 @@ openerp.mail = function (session) {
this.reinit();
},
/* return true if all file are complete else return false and make an alert */
do_check_attachment_upload: function () {
if (_.find(this.attachment_ids, function (file) {return file.upload;})) {
this.do_warn(session.web.qweb.render('mail.error_upload'), session.web.qweb.render('mail.error_upload_please_wait'));
return false;
} else {
return true;
}
},
/*post a message and fetch the message*/
on_message_post: function (event) {
var self = this;
var comment_node = this.$('textarea');
var body = comment_node.val();
comment_node.val('');
var attachments=[];
for (var i in this.attachment_ids) {
if (this.attachment_ids[i].upload) {
session.web.dialog($('<div>' + session.web.qweb.render('CrashManager.warning', {message: 'Please, wait while the file is uploading.'}) + '</div>'));
return false;
}
attachments.push(this.attachment_ids[i].id);
}
if (body.match(/\S+/)) {
if (this.do_check_attachment_upload() && (this.attachment_ids.length || body.match(/\S+/))) {
//session.web.blockUI();
this.parent_thread.ds_thread.call('message_post_user_api', [
this.context.default_res_id,
body,
false,
this.context.default_parent_id,
attachments,
_.map(this.attachment_ids, function (file) {return file.id;}),
this.parent_thread.context
]).done(function (record) {
var thread = self.parent_thread;
@ -571,8 +586,8 @@ openerp.mail = function (session) {
var message = thread.create_message_object( data[0] );
// insert the message on dom
thread.insert_message( message, root ? undefined : self.$el, root );
self.on_cancel();
});
self.on_cancel();
//session.web.unblockUI();
});
return true;

View File

@ -75,7 +75,7 @@
<t t-foreach='widget.attachment_ids' t-as='attachment'>
<t t-if="attachment.filetype !== 'webimage'">
<div t-attf-class="oe_attachment #{attachment.upload ? 'oe_uploading' : ''}">
<a t-att-href='attachment.url'>
<a t-att-href='attachment.url' target="_blank">
<img t-att-src="'/mail/static/src/img/mimetypes/' + attachment.filetype + '.png'"></img>
<div class='oe_name'><t t-raw='attachment.name' /></div>
</a>
@ -87,7 +87,7 @@
</t>
<t t-if="attachment.filetype === 'webimage'">
<div t-attf-class="oe_attachment oe_preview #{attachment.upload ? 'oe_uploading' : ''}">
<a t-att-href='attachment.url'>
<a t-att-href='attachment.url' target="_blank">
<img t-att-src="widget.attachments_resize_image(attachment.id, [100,80])"></img>
<div class='oe_name'><t t-raw='attachment.name' /></div>
</a>
@ -179,6 +179,12 @@
<div class="oe_view_nocontent">No messages.</div>
</t>
<!--
error message for uploading
-->
<t t-name="mail.error_upload">Uploading error</t>
<t t-name="mail.error_upload_please_wait">Please, wait while the file is uploading.</t>
<!--
record_thread main template
Template used to display the communication history in documents

View File

@ -421,6 +421,10 @@ class test_mail(test_mail_mockup.TestMailMockups):
self.assertEqual(attach.res_id, self.group_pigs_id, 'mail.message attachment res_id incorrect')
self.assertIn((attach.name, attach.datas.decode('base64')), _attachments,
'mail.message attachment name / data incorrect')
# Test: download attachments
for attach in message.attachment_ids:
dl_attach = self.mail_message.download_attachment(cr, uid, id_message=message.id, attachment_id=attach.id)
self.assertIn(( dl_attach['filename'], dl_attach['base64'].decode('base64') ), _attachments, 'mail.message download_attachment is incorrect')
# 3. Reply to the last message, check that its parent will be the first message
msg_id3 = self.mail_group.message_post(cr, uid, self.group_pigs_id, body='Test', parent_id=msg_id2)

View File

@ -31,6 +31,7 @@ class test_mail_access_rights(test_mail_mockup.TestMailMockups):
cr, uid = self.cr, self.uid
self.mail_group = self.registry('mail.group')
self.mail_message = self.registry('mail.message')
self.attachment = self.registry('ir.attachment')
self.mail_notification = self.registry('mail.notification')
self.res_users = self.registry('res.users')
self.res_groups = self.registry('res.groups')
@ -97,12 +98,16 @@ class test_mail_access_rights(test_mail_mockup.TestMailMockups):
self.mail_group.message_post(cr, uid, self.group_pigs_id, body='Message')
self.group_jobs_id = self.mail_group.create(cr, uid, {'name': 'Jobs', 'public': 'public'})
# prepare an attachment
attachment_id = self.attachment.create(cr, uid, {'datas': 'My attachment'.encode('base64'), 'name': 'doc.txt', 'datas_fname': 'doc.txt' })
# ----------------------------------------
# CASE1: Bert, basic mail.message read access
# ----------------------------------------
# Do: create a new mail.message
message_id = self.mail_message.create(cr, uid, {'body': 'My Body'})
message_id = self.mail_message.create(cr, uid, {'body': 'My Body', 'attachment_ids': [4, attachment_id] })
# Test: Bert reads the message, crash because not notification/not in doc followers/not read on doc
self.assertRaises(except_orm, self.mail_message.read,
cr, user_bert_id, message_id)
@ -110,11 +115,16 @@ class test_mail_access_rights(test_mail_mockup.TestMailMockups):
notif_id = self.mail_notification.create(cr, uid, {'message_id': message_id, 'partner_id': partner_bert_id})
# Test: Bert reads the message, ok because notification pushed
self.mail_message.read(cr, user_bert_id, message_id)
# Test: Bert download attachment, ok because he can read message
self.mail_message.download_attachment(cr, user_bert_id, message_id, attachment_id)
# Do: remove notification
self.mail_notification.unlink(cr, uid, notif_id)
# Test: Bert reads the message, crash because not notification/not in doc followers/not read on doc
self.assertRaises(except_orm, self.mail_message.read,
cr, self.user_bert_id, message_id)
# Test: Bert download attachment, crash because he can't read message
self.assertRaises(except_orm, self.mail_message.download_attachment,
cr, user_bert_id, message_id, attachment_id)
# Do: Bert is now the author
self.mail_message.write(cr, uid, [message_id], {'author_id': partner_bert_id})
# Test: Bert reads the message, ok because Bert is the author

View File

@ -7,3 +7,4 @@ access_res_partner_category,res.partner_category,base.model_res_partner_category
access_res_partner_title,res.partner_title,base.model_res_partner_title,portal.group_portal,1,0,0,0
access_acquirer,portal.payment.acquirer,portal.model_portal_payment_acquirer,,1,0,0,0
access_acquirer_all,portal.payment.acquirer,portal.model_portal_payment_acquirer,base.group_system,1,1,1,1
access_ir_attachment_group_portal,ir.attachment group_portal,base.model_ir_attachment,portal.group_portal,1,0,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
7 access_res_partner_title res.partner_title base.model_res_partner_title portal.group_portal 1 0 0 0
8 access_acquirer portal.payment.acquirer portal.model_portal_payment_acquirer 1 0 0 0
9 access_acquirer_all portal.payment.acquirer portal.model_portal_payment_acquirer base.group_system 1 1 1 1
10 access_ir_attachment_group_portal ir.attachment group_portal base.model_ir_attachment portal.group_portal 1 0 1 0