[MERGE] 'Invite & Quick Create User' update. Addons branch; see server branch for more details.
Quick Create: - [ADD] in context of 'user_id' fields the xml_ids of necessary groups, Invite: - [ADD] added send_mail boolean field on invite wizard, allowing to avoid sending emails when inviting someone as a follower on the document, - [IMP] notification and invite signature: improved signature (now including: sender name, company name as a link to the company website); invite message and subject improved, small code re-organization Misc: - [IMP] sheet tags added in various form views in HR bzr revid: tde@openerp.com-20130318121439-xyl34r9tdut6t19c
This commit is contained in:
commit
00bb2273d9
|
@ -19,11 +19,9 @@
|
|||
</header>
|
||||
</xpath>
|
||||
<!-- add Reset Password button -->
|
||||
<xpath expr="//div[@class='oe_right oe_button_box']" position="replace">
|
||||
<div class="oe_right oe_button_box">
|
||||
<xpath expr="//div[@class='oe_right oe_button_box']//button" position="replace">
|
||||
<button string="Send Reset Password Instructions"
|
||||
type="object" name="action_reset_password" />
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -151,7 +151,8 @@
|
|||
-->
|
||||
</group>
|
||||
<group>
|
||||
<field name="user_id"/>
|
||||
<field name="user_id"
|
||||
context="{'default_groups_ref': ['base.group_user', 'base.group_sale_salesman_all_leads']}"/>
|
||||
<label for="section_id"/>
|
||||
<div>
|
||||
<field name="section_id"/>
|
||||
|
@ -426,7 +427,7 @@
|
|||
</group>
|
||||
|
||||
<group>
|
||||
<field name="user_id"/>
|
||||
<field name="user_id" context="{'default_groups_ref': ['base.group_user', 'base.group_sale_salesman_all_leads']}"/>
|
||||
<label for="section_id"/>
|
||||
<div>
|
||||
<field name="section_id" widget="selection"/>
|
||||
|
@ -436,7 +437,7 @@
|
|||
<group>
|
||||
<field name="categ_ids"
|
||||
string="Categories" widget="many2many_tags"
|
||||
context = "{'object_name': 'crm.lead'}"
|
||||
context="{'object_name': 'crm.lead'}"
|
||||
domain="[('object_id.model', '=', 'crm.lead')]"/>
|
||||
|
||||
</group>
|
||||
|
|
|
@ -49,7 +49,8 @@
|
|||
</group>
|
||||
<group>
|
||||
<field name="company_id" groups="base.group_multi_company" on_change="onchange_company(company_id)"/>
|
||||
<field name="user_id" on_change="onchange_user(user_id)" string="Related User"/>
|
||||
<field name="user_id" on_change="onchange_user(user_id)" string="Related User"
|
||||
context="{'default_groups_ref': ['base.group_user']}"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="notes" placeholder="Other Information ..." colspan="4"/>
|
||||
|
|
|
@ -374,6 +374,7 @@
|
|||
<field name="model">hr.holidays.status</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Leave Type" version="7.0">
|
||||
<sheet string="Leave Type">
|
||||
<group col="4">
|
||||
<field name="name"/>
|
||||
<field name="categ_id"/>
|
||||
|
@ -392,6 +393,7 @@
|
|||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -107,7 +107,8 @@
|
|||
<field name="type_id" placeholder="Degree"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="user_id"/>
|
||||
<field name="user_id"
|
||||
context="{'default_groups_ref': ['base.group_user', 'base.group_hr_manager']}"/>
|
||||
<label for="title_action"/>
|
||||
<div>
|
||||
<field name="date_action"/>
|
||||
|
@ -341,6 +342,7 @@
|
|||
<field name="model">hr.recruitment.stage</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Stage" version="7.0">
|
||||
<sheet>
|
||||
<group string="Stage Definition">
|
||||
<group>
|
||||
<field name="name"/>
|
||||
|
@ -354,6 +356,7 @@
|
|||
</group>
|
||||
<separator string="Requirements"/>
|
||||
<field name="requirements"/>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -399,10 +402,12 @@
|
|||
<field name="model">hr.recruitment.degree</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Degree" version="7.0">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="sequence" groups="base.group_no_one"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -436,8 +441,12 @@
|
|||
<field name="name">hr.recruitment.source.form</field>
|
||||
<field name="model">hr.recruitment.source</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Sources of Applicants">
|
||||
<field name="name"/>
|
||||
<form string="Sources of Applicants" version="7.0">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
<field name="arch" type="xml">
|
||||
<tree editable="top" string="Timesheet Activities">
|
||||
<field name="date" on_change="on_change_date(date)"/>
|
||||
<field name="user_id" on_change="on_change_user_id(user_id)" required="1" options='{"no_open": True}'/>
|
||||
<field name="user_id" on_change="on_change_user_id(user_id)" required="1" options='{"no_open": True}'
|
||||
context="{'default_groups_ref': [base.group_user']}"/>
|
||||
<field name="name"/>
|
||||
<field domain="[('type','=','normal'),('use_timesheets','=',1)]" name="account_id" context="{'default_use_timesheets': 1, 'default_type': 'contract'}"/>
|
||||
<field name="unit_amount" string="Duration" on_change="on_change_unit_amount(product_id, unit_amount, False, product_uom_id,journal_id)" sum="Total time" widget="float_time"/>
|
||||
|
@ -29,7 +30,8 @@
|
|||
<group>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="user_id" on_change="on_change_user_id(user_id)" required="1"/>
|
||||
<field name="user_id" on_change="on_change_user_id(user_id)" required="1"
|
||||
context="{'default_groups_ref': [base.group_user']}"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="date" on_change="on_change_date(date)"/>
|
||||
|
|
|
@ -324,7 +324,8 @@
|
|||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name='user_id'/>
|
||||
<field name='user_id'
|
||||
context="{'default_groups_ref': ['base.group_user', 'lunch.group_lunch_user']}"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name='date'/>
|
||||
|
@ -409,7 +410,8 @@
|
|||
<form string="cashmove form" version="7.0">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="user_id"/>
|
||||
<field name="user_id"
|
||||
context="{'default_groups_ref': ['base.group_user', 'lunch.group_lunch_user']}"/>
|
||||
<field name="date"/>
|
||||
<field name="amount"/>
|
||||
</group>
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
##############################################################################
|
||||
from openerp.osv import osv, fields
|
||||
from openerp import tools, SUPERUSER_ID
|
||||
from openerp.tools.translate import _
|
||||
from openerp.tools.mail import plaintext2html
|
||||
|
||||
class mail_followers(osv.Model):
|
||||
""" mail_followers holds the data related to the follow mechanism inside
|
||||
|
@ -105,6 +107,43 @@ class mail_notification(osv.Model):
|
|||
notify_pids.append(partner.id)
|
||||
return notify_pids
|
||||
|
||||
def get_signature_footer(self, cr, uid, user_id, res_model=None, res_id=None, context=None):
|
||||
""" Format a standard footer for notification emails (such as pushed messages
|
||||
notification or invite emails).
|
||||
Format:
|
||||
<p>--<br />
|
||||
Administrator
|
||||
</p>
|
||||
<div>
|
||||
<small>Send by <a ...>Your Company</a> using <a ...>OpenERP</a>.</small> OR
|
||||
<small>Send by Administrator using <a ...>OpenERP</a>.</small>
|
||||
</div>
|
||||
"""
|
||||
footer = ""
|
||||
if not user_id:
|
||||
return footer
|
||||
|
||||
# add user signature
|
||||
user = self.pool.get("res.users").browse(cr, SUPERUSER_ID, [user_id], context=context)[0]
|
||||
if user.signature:
|
||||
signature = plaintext2html(user.signature)
|
||||
else:
|
||||
signature = "--<br />%s" % user.name
|
||||
footer = tools.append_content_to_html(footer, signature, plaintext=False, container_tag='p')
|
||||
|
||||
# add company signature
|
||||
if user.company_id:
|
||||
company = user.company_id.website and "<a style='color:inherit' href='%s'>%s</a>" % (user.company_id.website, user.company_id.name) or user.company_id.name
|
||||
else:
|
||||
company = user.name
|
||||
signature_company = _('<small>Send by %(company)s using %(openerp)s.</small>' % {
|
||||
'company': company,
|
||||
'openerp': "<a style='color:inherit' href='https://www.openerp.com/'>OpenERP</a>"
|
||||
})
|
||||
footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag='div')
|
||||
|
||||
return footer
|
||||
|
||||
def _notify(self, cr, uid, msg_id, partners_to_notify=None, context=None):
|
||||
""" Send by email the notification depending on the user preferences
|
||||
|
||||
|
@ -141,14 +180,11 @@ class mail_notification(osv.Model):
|
|||
# TDE FIXME: commented, to be improved in a future branch
|
||||
# quote_context = self.pool.get('mail.message').message_quote_context(cr, uid, msg_id, context=context)
|
||||
|
||||
mail_mail = self.pool.get('mail.mail')
|
||||
# add signature
|
||||
body_html = msg.body
|
||||
# if quote_context:
|
||||
# body_html = tools.append_content_to_html(body_html, quote_context, plaintext=False)
|
||||
signature = msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0].signature or ''
|
||||
if signature:
|
||||
body_html = tools.append_content_to_html(body_html, signature, plaintext=True, container_tag='div')
|
||||
user_id = msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0] and msg.author_id.user_ids[0].id or None
|
||||
signature_company = self.get_signature_footer(cr, uid, user_id, res_model=msg.model, res_id=msg.res_id, context=context)
|
||||
body_html = tools.append_content_to_html(body_html, signature_company, plaintext=False, container_tag='div')
|
||||
|
||||
# email_from: partner-user alias or partner email or mail.message email_from
|
||||
if msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0].alias_domain and msg.author_id.user_ids[0].alias_name:
|
||||
|
@ -164,6 +200,7 @@ class mail_notification(osv.Model):
|
|||
'body_html': body_html,
|
||||
'email_from': email_from,
|
||||
}
|
||||
mail_mail = self.pool.get('mail.mail')
|
||||
email_notif_id = mail_mail.create(cr, uid, mail_values, context=context)
|
||||
try:
|
||||
return mail_mail.send(cr, uid, [email_notif_id], recipient_ids=notify_partner_ids, context=context)
|
||||
|
|
|
@ -160,15 +160,12 @@ class mail_mail(osv.Model):
|
|||
return 'Re: %s' % (mail.record_name)
|
||||
return mail.subject
|
||||
|
||||
def send_get_mail_body(self, cr, uid, mail, partner=None, context=None):
|
||||
""" Return a specific ir_email body. The main purpose of this method
|
||||
is to be inherited by Portal, to add a link for signing in, in
|
||||
def send_get_mail_body_footer(self, cr, uid, mail, partner=None, context=None):
|
||||
""" Return a specific footer for the ir_email body. The main purpose of this method
|
||||
is to be inherited by Portal, to add modify the link for signing in, in
|
||||
each notification email a partner receives.
|
||||
|
||||
:param browse_record mail: mail.mail browse_record
|
||||
:param browse_record partner: specific recipient partner
|
||||
"""
|
||||
body = mail.body_html
|
||||
body_footer = ""
|
||||
# partner is a user, link to a related document (incentive to install portal)
|
||||
if partner and partner.user_ids and mail.model and mail.res_id \
|
||||
and self.check_access_rights(cr, partner.user_ids[0].id, 'read', raise_exception=False):
|
||||
|
@ -184,10 +181,23 @@ class mail_mail(osv.Model):
|
|||
'id': mail.res_id,
|
||||
}
|
||||
url = urljoin(base_url, "?%s#%s" % (urlencode(query), urlencode(fragment)))
|
||||
text = _("""<p>Access this document <a href="%s">directly in OpenERP</a></p>""") % url
|
||||
body = tools.append_content_to_html(body, ("<div><p>%s</p></div>" % text), plaintext=False)
|
||||
body_footer = _("""<small>Access this document <a style='color:inherit' href="%s">directly in OpenERP</a></small>""") % url
|
||||
except except_orm, e:
|
||||
pass
|
||||
return body_footer
|
||||
|
||||
def send_get_mail_body(self, cr, uid, mail, partner=None, context=None):
|
||||
""" Return a specific ir_email body. The main purpose of this method
|
||||
is to be inherited to add custom content depending on some module.
|
||||
|
||||
:param browse_record mail: mail.mail browse_record
|
||||
:param browse_record partner: specific recipient partner
|
||||
"""
|
||||
body = mail.body_html
|
||||
|
||||
# add footer
|
||||
body_footer = self.send_get_mail_body_footer(cr, uid, mail, partner=partner, context=context)
|
||||
body = tools.append_content_to_html(body, body_footer, plaintext=False, container_tag='div')
|
||||
return body
|
||||
|
||||
def send_get_mail_reply_to(self, cr, uid, mail, partner=None, context=None):
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<field name="inherit_id" ref="base.view_users_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<field name="email" position="before">
|
||||
<field name="signature" position="before">
|
||||
<field name="notification_email_send"/>
|
||||
</field>
|
||||
<field name="email" position="after">
|
||||
|
|
|
@ -561,6 +561,14 @@
|
|||
text-align: center;
|
||||
width:100%;
|
||||
}
|
||||
.openerp .oe_followers button.oe_invite{
|
||||
margin: 5px 0;
|
||||
padding: 2px 8px;
|
||||
font-size: 12px;
|
||||
text-shadow: none;
|
||||
width: 100%;
|
||||
}
|
||||
.openerp .oe_followers button.oe_invite,
|
||||
.openerp .oe_followers button.oe_follower.oe_following{
|
||||
color: white;
|
||||
background-color: #3465A4;
|
||||
|
@ -614,9 +622,6 @@
|
|||
margin-top: 12px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.openerp .oe_followers .oe_invite{
|
||||
float: right;
|
||||
}
|
||||
.openerp .oe_followers .oe_partner {
|
||||
height: 32px;
|
||||
overflow: hidden;
|
||||
|
|
|
@ -220,23 +220,16 @@ openerp_mail_followers = function(session, mail) {
|
|||
/** Display subtypes: {'name': default, followed} */
|
||||
display_subtypes:function (data, id) {
|
||||
var self = this;
|
||||
var subtype_list_ul = this.$('.oe_subtype_list');
|
||||
var records = [];
|
||||
var nb_subtype = 0;
|
||||
subtype_list_ul.empty();
|
||||
if (data[id]) {
|
||||
records = data[id].message_subtype_data;
|
||||
}
|
||||
_(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();
|
||||
var $list = this.$('.oe_subtype_list');
|
||||
$list.empty().hide();
|
||||
var records = data[this.view.datarecord.id || this.view.dataset.ids[0]].message_subtype_data;
|
||||
_(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') );
|
||||
});
|
||||
if (_.size(records) > 1) {
|
||||
$list.show();
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -17,10 +17,9 @@
|
|||
</t>
|
||||
<div class="oe_subtype_list"></div>
|
||||
</div>
|
||||
<hr size="2"></hr>
|
||||
<div class='oe_follower_title_box'>
|
||||
<h4 class='oe_follower_title'>Followers</h4>
|
||||
<a t-if="widget.view_is_editable" href='#' class="oe_invite">Add others</a>
|
||||
<button t-if="widget.view_is_editable" href='#' class="oe_invite">Invite people</button>
|
||||
</div>
|
||||
<div class="oe_follower_list"></div>
|
||||
</div>
|
||||
|
|
|
@ -31,18 +31,18 @@ class test_invite(TestMailBase):
|
|||
# Do: create a mail_wizard_invite, validate it
|
||||
self._init_mock_build_email()
|
||||
context = {'default_res_model': 'mail.group', 'default_res_id': self.group_pigs_id}
|
||||
mail_invite_id = mail_invite.create(cr, self.user_raoul_id, {'partner_ids': [(4, self.partner_bert_id)]}, context)
|
||||
mail_invite_id = mail_invite.create(cr, self.user_raoul_id, {'partner_ids': [(4, self.partner_bert_id)], 'send_mail': True}, context)
|
||||
mail_invite.add_followers(cr, self.user_raoul_id, [mail_invite_id], {'default_model': 'mail.group', 'default_res_id': 0})
|
||||
|
||||
# Test: Pigs followers should contain Admin, Bert
|
||||
self.group_pigs.refresh()
|
||||
follower_ids = [follower.id for follower in self.group_pigs.message_follower_ids]
|
||||
self.assertEqual(set(follower_ids), set([self.partner_admin_id, self.partner_bert_id]), 'Pigs followers after invite is incorrect')
|
||||
self.assertEqual(set(follower_ids), set([self.partner_admin_id, self.partner_bert_id]), 'invite: Pigs followers after invite is incorrect')
|
||||
|
||||
# Test: (pretend to) send email and check subject, body
|
||||
self.assertEqual(len(self._build_email_kwargs_list), 1, 'sent email number incorrect, should be only for Bert')
|
||||
for sent_email in self._build_email_kwargs_list:
|
||||
self.assertEqual(sent_email.get('subject'), 'Invitation to follow Pigs',
|
||||
'subject of invitation email is incorrect')
|
||||
self.assertTrue('You have been invited to follow Pigs' in sent_email.get('body'),
|
||||
'body of invitation email is incorrect')
|
||||
self.assertEqual(sent_email.get('subject'), 'Invitation to follow Discussion group: Pigs',
|
||||
'invite: subject of invitation email is incorrect')
|
||||
self.assertIn('Raoul Grosbedon invited you to follow Discussion group document: Pigs', sent_email.get('body'),
|
||||
'invite: body of invitation email is incorrect')
|
||||
|
|
|
@ -84,23 +84,6 @@ Sylvie
|
|||
|
||||
class test_mail(TestMailBase):
|
||||
|
||||
def _mock_send_get_mail_body(self, *args, **kwargs):
|
||||
# def _send_get_mail_body(self, cr, uid, mail, partner=None, context=None)
|
||||
body = append_content_to_html(args[2].body_html, kwargs.get('partner').name if kwargs.get('partner') else 'No specific partner', plaintext=False)
|
||||
return body
|
||||
|
||||
def setUp(self):
|
||||
super(test_mail, self).setUp()
|
||||
|
||||
# Mock send_get_mail_body to test its functionality without other addons override
|
||||
self._send_get_mail_body = self.registry('mail.mail').send_get_mail_body
|
||||
self.registry('mail.mail').send_get_mail_body = self._mock_send_get_mail_body
|
||||
|
||||
def tearDown(self):
|
||||
# Remove mocks
|
||||
self.registry('mail.mail').send_get_mail_body = self._send_get_mail_body
|
||||
super(test_mail, self).tearDown()
|
||||
|
||||
def test_00_message_process(self):
|
||||
""" Testing incoming emails processing. """
|
||||
cr, uid, user_raoul = self.cr, self.uid, self.user_raoul
|
||||
|
@ -341,11 +324,15 @@ class test_mail(TestMailBase):
|
|||
_subject = 'Pigs'
|
||||
_mail_subject = 'Re: %s' % (group_pigs.name)
|
||||
_body1 = '<p>Pigs rules</p>'
|
||||
_mail_body1 = '<p>Pigs rules</p>\n<div><p>Raoul</p></div>\n'
|
||||
_mail_bodyalt1 = 'Pigs rules\nRaoul\n'
|
||||
_mail_body1 = '<p>Pigs rules</p>'
|
||||
_mail_signature1 = '<p>Raoul</p>'
|
||||
_mail_bodyalt1 = 'Pigs rules\n'
|
||||
_mail_signaturealt1 = '\nRaoul\n'
|
||||
_body2 = '<html>Pigs rules</html>'
|
||||
_mail_body2 = '<div><p>Pigs rules</p></div>\n<div><p>Raoul</p></div>'
|
||||
_mail_bodyalt2 = 'Pigs rules\nRaoul'
|
||||
_mail_body2 = '<div><p>Pigs rules</p></div>'
|
||||
_mail_signature2 = '<p>Raoul</p>'
|
||||
_mail_bodyalt2 = 'Pigs rules\n'
|
||||
_mail_signaturealt2 = '\nRaoul\n'
|
||||
_attachments = [('First', 'My first attachment'), ('Second', 'My second attachment')]
|
||||
|
||||
# ----------------------------------------
|
||||
|
@ -366,12 +353,14 @@ class test_mail(TestMailBase):
|
|||
self.assertEqual(len(sent_emails), 2, 'sent_email number of sent emails incorrect')
|
||||
for sent_email in sent_emails:
|
||||
self.assertEqual(sent_email['subject'], _subject, 'sent_email subject incorrect')
|
||||
self.assertTrue(sent_email['body'] in [_mail_body1 + '\nBert Tartopoils\n', _mail_body1 + '\nAdministrator\n'],
|
||||
'sent_email body incorrect')
|
||||
self.assertIn(_mail_body1, sent_email['body'], 'sent_email body incorrect')
|
||||
self.assertIn(_mail_signature1, sent_email['body'], 'sent_email body incorrect (no signature)')
|
||||
self.assertIn("OpenERP", sent_email['body'], 'sent_email body incorrect (no OpenERP company)')
|
||||
# the html2plaintext uses etree or beautiful soup, so the result may be slighly different
|
||||
# depending if you have installed beautiful soup.
|
||||
self.assertTrue(sent_email['body_alternative'] in [_mail_bodyalt1 + '\nBert Tartopoils\n', _mail_bodyalt1 + '\nAdministrator\n'],
|
||||
'sent_email body_alternative is incorrect')
|
||||
self.assertIn(_mail_bodyalt1, sent_email['body_alternative'], 'sent_email body_alternative is incorrect')
|
||||
self.assertIn(_mail_signaturealt1, sent_email['body_alternative'], 'sent_email body_alternative is incorrect (no signature)')
|
||||
self.assertIn("OpenERP", sent_email['body_alternative'], 'sent_email body incorrect (no OpenERP company)')
|
||||
# Test: mail_message: notified_partner_ids = group followers
|
||||
message_pids = set([partner.id for partner in message1.notified_partner_ids])
|
||||
test_pids = set([self.partner_admin_id, p_b_id, p_c_id])
|
||||
|
@ -405,7 +394,12 @@ class test_mail(TestMailBase):
|
|||
for sent_email in sent_emails:
|
||||
self.assertEqual(sent_email['subject'], _mail_subject, 'sent_email subject incorrect')
|
||||
self.assertIn(_mail_body2, sent_email['body'], 'sent_email body incorrect')
|
||||
self.assertIn(_mail_bodyalt2, sent_email['body_alternative'], 'sent_email body_alternative incorrect')
|
||||
self.assertIn(_mail_signature2, sent_email['body'], 'sent_email body incorrect (no signature)')
|
||||
self.assertIn("OpenERP", sent_email['body'], 'sent_email body incorrect (no OpenERP company)')
|
||||
# body_alternative
|
||||
self.assertIn(_mail_bodyalt2, sent_email['body_alternative'], 'sent_email body_alternative is incorrect')
|
||||
self.assertIn(_mail_signaturealt2, sent_email['body_alternative'], 'sent_email body_alternative is incorrect (no signature)')
|
||||
self.assertIn("OpenERP", sent_email['body'], 'sent_email body incorrect (no OpenERP company)')
|
||||
# Test: mail_message: notified_partner_ids = group followers
|
||||
message_pids = set([partner.id for partner in message2.notified_partner_ids])
|
||||
test_pids = set([self.partner_admin_id, p_b_id, p_c_id, p_d_id])
|
||||
|
|
|
@ -32,12 +32,19 @@ class invite_wizard(osv.osv_memory):
|
|||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
result = super(invite_wizard, self).default_get(cr, uid, fields, context=context)
|
||||
if 'message' in fields and result.get('res_model') and result.get('res_id'):
|
||||
document_name = self.pool.get(result.get('res_model')).name_get(cr, uid, [result.get('res_id')], context=context)[0][1]
|
||||
message = _('<div>You have been invited to follow %s.</div>' % document_name)
|
||||
user_name = self.pool.get('res.users').name_get(cr, uid, [uid], context=context)[0][1]
|
||||
model = result.get('res_model')
|
||||
res_id = result.get('res_id')
|
||||
if 'message' in fields and model and res_id:
|
||||
ir_model = self.pool.get('ir.model')
|
||||
model_ids = ir_model.search(cr, uid, [('model', '=', self.pool.get(model)._name)], context=context)
|
||||
model_name = ir_model.name_get(cr, uid, model_ids, context=context)[0][1]
|
||||
|
||||
document_name = self.pool.get(model).name_get(cr, uid, [res_id], context=context)[0][1]
|
||||
message = _('<div><p>Hello,</p><p>%s invited you to follow %s document: %s.<p></div>') % (user_name, model_name, document_name)
|
||||
result['message'] = message
|
||||
elif 'message' in fields:
|
||||
result['message'] = _('<div>You have been invited to follow a new document.</div>')
|
||||
result['message'] = _('<div><p>Hello,</p><p>%s invited you to follow a new document.</p></div>') % user_name
|
||||
return result
|
||||
|
||||
_columns = {
|
||||
|
@ -46,8 +53,12 @@ class invite_wizard(osv.osv_memory):
|
|||
help='Model of the followed resource'),
|
||||
'res_id': fields.integer('Related Document ID', select=1,
|
||||
help='Id of the followed resource'),
|
||||
'partner_ids': fields.many2many('res.partner', string='Partners'),
|
||||
'partner_ids': fields.many2many('res.partner', string='Recipients',
|
||||
help="List of partners that will be added as follower of the current document."),
|
||||
'message': fields.html('Message'),
|
||||
'send_mail': fields.boolean('Send Email',
|
||||
help="If checked, the partners will receive an email warning they have been "
|
||||
"added in the document's followers."),
|
||||
}
|
||||
|
||||
def add_followers(self, cr, uid, ids, context=None):
|
||||
|
@ -59,21 +70,25 @@ class invite_wizard(osv.osv_memory):
|
|||
new_follower_ids = [p.id for p in wizard.partner_ids if p not in document.message_follower_ids]
|
||||
model_obj.message_subscribe(cr, uid, [wizard.res_id], new_follower_ids, context=context)
|
||||
|
||||
# send an email
|
||||
if wizard.message:
|
||||
ir_model = self.pool.get('ir.model')
|
||||
model_ids = ir_model.search(cr, uid, [('model', '=', model_obj._name)], context=context)
|
||||
model_name = ir_model.name_get(cr, uid, model_ids, context=context)[0][1]
|
||||
|
||||
# send an email if option checked and if a message exists (do not send void emails)
|
||||
if wizard.send_mail and wizard.message:
|
||||
# add signature
|
||||
user_id = self.pool.get("res.users").read(cr, uid, [uid], fields=["signature"], context=context)[0]
|
||||
signature = user_id and user_id["signature"] or ''
|
||||
if signature:
|
||||
wizard.message = tools.append_content_to_html(wizard.message, signature, plaintext=True, container_tag='div')
|
||||
# FIXME 8.0: use notification_email_send, send a wall message and let mail handle email notification + message box
|
||||
signature_company = self.pool.get('mail.notification').get_signature_footer(cr, uid, user_id=uid, res_model=wizard.res_model, res_id=wizard.res_id, context=context)
|
||||
wizard.message = tools.append_content_to_html(wizard.message, signature_company, plaintext=False, container_tag='div')
|
||||
|
||||
# send mail to new followers
|
||||
for follower_id in new_follower_ids:
|
||||
mail_mail = self.pool.get('mail.mail')
|
||||
# the invite wizard should create a private message not related to any object -> no model, no res_id
|
||||
mail_id = mail_mail.create(cr, uid, {
|
||||
'model': wizard.res_model,
|
||||
'res_id': wizard.res_id,
|
||||
'subject': 'Invitation to follow %s' % document.name_get()[0][1],
|
||||
'subject': _('Invitation to follow %s: %s') % (model_name, document.name_get()[0][1]),
|
||||
'body_html': '%s' % wizard.message,
|
||||
'auto_delete': True,
|
||||
}, context=context)
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
<field name="partner_ids" widget="many2many_tags_email"
|
||||
placeholder="Add contacts to notify..."
|
||||
context="{'force_email':True, 'show_email':True}"/>
|
||||
<field name="message"/>
|
||||
<field name="send_mail"/>
|
||||
<field name="message" attrs="{'invisible': [('send_mail','!=',True)]}"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button string="Add Followers"
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
from openerp import SUPERUSER_ID
|
||||
from openerp.osv import osv
|
||||
from openerp.osv.orm import except_orm
|
||||
from openerp.tools import append_content_to_html
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
|
@ -30,18 +29,17 @@ class mail_mail(osv.Model):
|
|||
""" Update of mail_mail class, to add the signin URL to notifications. """
|
||||
_inherit = 'mail.mail'
|
||||
|
||||
def send_get_mail_body(self, cr, uid, mail, partner=None, context=None):
|
||||
def send_get_mail_body_footer(self, cr, uid, mail, partner=None, context=None):
|
||||
""" add a signin link inside the body of a mail.mail
|
||||
:param mail: mail.mail browse_record
|
||||
:param partner: browse_record of the specific recipient partner
|
||||
:return: the resulting body_html
|
||||
"""
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
body = mail.body_html
|
||||
if partner:
|
||||
contex_signup = dict(context or {}, signup_valid=True)
|
||||
partner = partner_obj.browse(cr, SUPERUSER_ID, partner.id, context=contex_signup)
|
||||
text = _("""<p>Access your messages and personal documents through <a href="%s">our Customer Portal</a></p>""") % partner.signup_url
|
||||
body_footer = _("""<small>Access your messages and documents through <a style='color:inherit' href="%s">our Customer Portal</a></small>""") % partner.signup_url
|
||||
# partner is an user: add a link to the document if read access
|
||||
if partner.user_ids and mail.model and mail.res_id \
|
||||
and self.check_access_rights(cr, partner.user_ids[0].id, 'read', raise_exception=False):
|
||||
|
@ -49,8 +47,9 @@ class mail_mail(osv.Model):
|
|||
try:
|
||||
self.pool.get(mail.model).check_access_rule(cr, related_user.id, [mail.res_id], 'read', context=context)
|
||||
url = partner_obj._get_signup_url_for_action(cr, related_user.id, [partner.id], action='', res_id=mail.res_id, model=mail.model, context=context)[partner.id]
|
||||
text = _("""<p>Access this document <a href="%s">directly in OpenERP</a></p>""") % url
|
||||
text = _("""<small>Access this document <a style='color:inherit' href="%s">directly in OpenERP</a></small>""") % url
|
||||
except except_orm, e:
|
||||
pass
|
||||
body = append_content_to_html(body, ("<div><p>%s</p></div>" % text), plaintext=False)
|
||||
return body
|
||||
return body_footer
|
||||
else:
|
||||
return super(mail_mail, self).send_get_mail_body_footer(cr, uid, mail, partner=partner, context=context)
|
||||
|
|
|
@ -106,7 +106,7 @@ class test_portal(TestMailBase):
|
|||
# Do: create a mail_wizard_invite, validate it
|
||||
self._init_mock_build_email()
|
||||
context = {'default_res_model': 'mail.group', 'default_res_id': self.group_pigs_id}
|
||||
mail_invite_id = mail_invite.create(cr, uid, {'partner_ids': [(4, partner_carine_id)]}, context)
|
||||
mail_invite_id = mail_invite.create(cr, uid, {'partner_ids': [(4, partner_carine_id)], 'send_mail': True}, context)
|
||||
mail_invite.add_followers(cr, uid, [mail_invite_id])
|
||||
|
||||
# Test: Pigs followers should contain Admin and Bert
|
||||
|
@ -124,9 +124,9 @@ class test_portal(TestMailBase):
|
|||
# Test: (pretend to) send email and check subject, body
|
||||
self.assertEqual(len(self._build_email_kwargs_list), 1, 'sent email number incorrect, should be only for Bert')
|
||||
for sent_email in self._build_email_kwargs_list:
|
||||
self.assertEqual(sent_email.get('subject'), 'Invitation to follow Pigs',
|
||||
'subject of invitation email is incorrect')
|
||||
self.assertTrue('You have been invited to follow Pigs' in sent_email.get('body'),
|
||||
'body of invitation email is incorrect')
|
||||
self.assertEqual(sent_email.get('subject'), 'Invitation to follow Discussion group: Pigs',
|
||||
'invite: subject of invitation email is incorrect')
|
||||
self.assertIn('Administrator invited you to follow Discussion group document: Pigs', sent_email.get('body'),
|
||||
'invite: body of invitation email is incorrect')
|
||||
self.assertTrue(partner_carine.signup_url in sent_email.get('body'),
|
||||
'body of invitation email does not contain signup url')
|
||||
'invite: body of invitation email does not contain signup url')
|
||||
|
|
|
@ -109,7 +109,8 @@
|
|||
<group name="inventory">
|
||||
<group name="status" string="Status">
|
||||
<field name="state"/>
|
||||
<field name="product_manager"/>
|
||||
<field name="product_manager"
|
||||
context="{'default_groups_ref': ['base.group_user', 'base.group_sale_manager']}"/>
|
||||
</group>
|
||||
<group name="Weights" groups="product.group_stock_packaging" string="Weights">
|
||||
<field digits="(14, 3)" name="volume" attrs="{'readonly':[('type','=','service')]}"/>
|
||||
|
|
|
@ -100,7 +100,9 @@
|
|||
<group>
|
||||
<group>
|
||||
<field name="privacy_visibility"/>
|
||||
<field name="user_id" string="Project Manager" attrs="{'readonly':[('state','in',['close', 'cancelled'])]}"/>
|
||||
<field name="user_id" string="Project Manager"
|
||||
attrs="{'readonly':[('state','in',['close', 'cancelled'])]}"
|
||||
context="{'default_groups_ref': ['base.group_user', 'project.group_project_manager']}"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
|
||||
|
@ -381,7 +383,10 @@
|
|||
<group>
|
||||
<group>
|
||||
<field name="project_id" on_change="onchange_project(project_id)" context="{'default_use_tasks':1}"/>
|
||||
<field name="user_id" attrs="{'readonly':[('state','in',['done', 'cancelled'])]}" options='{"no_open": True}'/>
|
||||
<field name="user_id"
|
||||
attrs="{'readonly':[('state','in',['done', 'cancelled'])]}"
|
||||
options='{"no_open": True}'
|
||||
context="{'default_groups_ref': ['base.group_user', 'project.group_project_user']}"/>
|
||||
<field name="planned_hours" widget="float_time"
|
||||
groups="project.group_time_work_estimation_tasks"
|
||||
on_change="onchange_planned(planned_hours, effective_hours)"/>
|
||||
|
|
|
@ -69,7 +69,8 @@
|
|||
<field name="categ_ids" widget="many2many_tags"/>
|
||||
<group>
|
||||
<group groups="base.group_user">
|
||||
<field name="user_id"/>
|
||||
<field name="user_id"
|
||||
context="{'default_groups_ref': ['base.group_user', 'project.group_project_user']}"/>
|
||||
<field name="partner_id" on_change="onchange_partner_id(partner_id, email_from)"/>
|
||||
<field name="email_from"/>
|
||||
<label for="project_id" groups="base.group_user"/>
|
||||
|
|
Loading…
Reference in New Issue