From cde9308d022d3f9d659a353efe970321da3e718c Mon Sep 17 00:00:00 2001 From: Niko Date: Thu, 27 Dec 2012 14:33:39 +0100 Subject: [PATCH 001/146] [IE] bug 1092869 bzr revid: nwi@openerp.com-20121227133339-to3uxdcuudc5ykyz --- addons/web/static/src/css/base.css | 14 ++++++++------ addons/web/static/src/css/base.sass | 2 ++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index 8a5aa5f9ad0..fea2b7d3c34 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -1,4 +1,4 @@ -@charset "utf-8"; +@charset "UTF-8"; @font-face { font-family: "mnmliconsRegular"; src: url("/web/static/src/font/mnmliconsv21-webfont.eot") format("eot"); @@ -30,7 +30,7 @@ text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5); /* http://www.quirksmode.org/dom/inputfile.html * http://stackoverflow.com/questions/2855589/replace-input-type-file-by-an-image - */ */ + */ } .openerp.openerp_webclient_container { height: 100%; @@ -1265,7 +1265,7 @@ color: white; padding: 2px 4px; margin: 1px 6px 0 0; - border: 1px solid lightGray; + border: 1px solid lightgrey; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); -moz-border-radius: 4px; -webkit-border-radius: 4px; @@ -1290,7 +1290,7 @@ transform: scale(1.1); } .openerp .oe_secondary_submenu .oe_active { - border-top: 1px solid lightGray; + border-top: 1px solid lightgrey; border-bottom: 1px solid #dedede; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2), inset 0 -1px 3px rgba(40, 40, 40, 0.2); @@ -2240,7 +2240,7 @@ } .openerp .oe_form .oe_form_label_help[for] span, .openerp .oe_form .oe_form_label[for] span { font-size: 80%; - color: darkGreen; + color: darkgreen; vertical-align: top; position: relative; top: -4px; @@ -3131,6 +3131,9 @@ div.ui-widget-overlay { border-radius: 3px; } +.openerp_ie .oe_form_binary_file { + width: 80px; +} .openerp_ie .oe_form_field_boolean input { background: white; } @@ -3291,7 +3294,6 @@ div.ui-widget-overlay { overflow: hidden !important; } } - .blockUI.blockOverlay { background-color: black; opacity: 0.6; diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass index 3aeba573041..5b1f69a31ad 100644 --- a/addons/web/static/src/css/base.sass +++ b/addons/web/static/src/css/base.sass @@ -2472,6 +2472,8 @@ div.ui-widget-overlay // Internet Explorer 9+ specifics {{{ .openerp_ie + .oe_form_binary_file + width: 80px .oe_form_field_boolean input background: #fff input[type='checkbox'] From ef1e8f54dd3137eaa76e4c53861c56ab57b40a7e Mon Sep 17 00:00:00 2001 From: "Bhumi Thakkar (Open ERP)" Date: Tue, 22 Jan 2013 17:19:32 +0530 Subject: [PATCH 003/146] [FIX] Date Picker is not translated into local language.--fixes:lp1101072 bzr revid: bth@tinyerp.com-20130122114932-o2jd05u247jlv02c --- addons/web/static/src/js/view_form.js | 36 +++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 01d4bf6dd33..4646963850c 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -2391,6 +2391,42 @@ instance.web.DateTimeWidget = instance.web.Widget.extend({ this.$input = this.$el.find('input.oe_datepicker_master'); this.$input_picker = this.$el.find('input.oe_datepicker_container'); + $.datepicker.setDefaults({ + clearText: _t('Clear'), + clearStatus: _t('Erase the current date'), + closeText: _t('Done'), + closeStatus: _t('Close without change'), + prevText: _t(''), + nextStatus: _t('Show the next month'), + currentText: _t('Today'), + currentStatus: _t('Show the current month'), + monthNames: Date.CultureInfo.monthNames, + monthNamesShort: Date.CultureInfo.abbreviatedMonthNames, + monthStatus: _t('Show a different month'), + yearStatus: _t('Show a different year'), + weekHeader: _t('Wk'), + weekStatus: _t('Week of the year'), + dayNames: Date.CultureInfo.dayNames, + dayNamesShort: Date.CultureInfo.abbreviatedDayNames, + dayNamesMin: Date.CultureInfo.shortestDayNames, + dayStatus: _t('Set DD as first week day'), + dateStatus: _t('Select D, M d'), + firstDay: Date.CultureInfo.firstDayOfWeek, + initStatus: _t('Select a date'), + isRTL: false + }); + $.timepicker.setDefaults({ + timeOnlyTitle: _t('Choose Time'), + timeText: _t('Time'), + hourText: _t('Hour'), + minuteText: _t('Minute'), + secondText: _t('Second'), + currentText: _t('Now'), + closeText: _t('Done') + }); + this.picker({ onClose: this.on_picker_select, onSelect: this.on_picker_select, From 468fed66be75eec5bc8b2af7a52373c38d09120b Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Thu, 24 Jan 2013 10:42:41 +0100 Subject: [PATCH 004/146] [IMP] mail: add a method get_signature_footer to add a good signature on bottom of messages sent with the chatter and invite followers bzr revid: chm@openerp.com-20130124094241-k9ophrwqhne611il --- addons/mail/mail_followers.py | 60 +++++++++++++++++++++++++++++++---- addons/mail/mail_mail.py | 2 +- addons/mail/wizard/invite.py | 7 ++-- addons/portal/mail_mail.py | 6 ++-- 4 files changed, 61 insertions(+), 14 deletions(-) diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py index ec9bc86d6c5..85adfae5d09 100644 --- a/addons/mail/mail_followers.py +++ b/addons/mail/mail_followers.py @@ -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 @@ -103,6 +105,54 @@ 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): + footer = "" + user = self.pool.get("res.users").browse(cr, uid, [user_id], context=context)[0] + if user and user.signature: + signature = plaintext2html(user.signature) + else: + signature = "--
%s" % user.name + footer = tools.append_content_to_html(footer, signature, plaintext=False, container_tag='p') + + company = None + if user.company_id: + company = user.company_id.website and "%s" % (user.company_id.website, user.company_id.name) or user.company_id.name + else: + company = user.name + + model_name = None + record_name = None + if res_model: + res_model_obj = self.pool.get('ir.model') + res_model_ids = res_model_obj.search(cr, uid, [('model', '=', res_model)], context=context) + model_name = res_model_obj.browse(cr, uid, res_model_ids, context=context)[0].name + if res_id: + record_obj = self.pool.get(res_model) + record = record_obj.browse(cr, uid, [res_id], context=context)[0] + record_name = record.name + + if company: + if model_name: + if record_name: + signature_company = _("This message is written on the document '%(record_name)s' of '%(model_name)s' from '%(company)s'." % { + 'record_name': record_name, + 'model_name': model_name, + 'company': company + }) + else: + signature_company = _("This message is written on '%(model_name)s' from '%(company)s'." % { + 'model_name': model_name, + 'company': company + }) + else: + signature_company = _("This message is written from '%(company)s'." % { + 'company': company + }) + + footer = tools.append_content_to_html(footer, "%s" % signature_company, plaintext=False, container_tag='div') + + return footer + def _notify(self, cr, uid, msg_id, context=None): """ Send by email the notification depending on the user preferences """ if context is None: @@ -120,14 +170,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 = msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0] or None + signature_company = self.get_signature_footer(cr, uid, user_id=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') mail_values = { 'mail_message_id': msg.id, @@ -137,6 +184,7 @@ class mail_notification(osv.Model): 'state': 'outgoing', } mail_values['email_to'] = ', '.join(mail_values['email_to']) + 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) diff --git a/addons/mail/mail_mail.py b/addons/mail/mail_mail.py index 7b8ec0b3579..d91c3f7a8cf 100644 --- a/addons/mail/mail_mail.py +++ b/addons/mail/mail_mail.py @@ -177,7 +177,7 @@ class mail_mail(osv.Model): 'id': mail.res_id, } url = urljoin(base_url, "?%s#%s" % (urlencode(query), urlencode(fragment))) - text = _("""

Access this document directly in OpenERP

""") % url + text = _("""Access this document directly in OpenERP""") % url body = tools.append_content_to_html(body, ("

%s

" % text), plaintext=False) except except_orm, e: pass diff --git a/addons/mail/wizard/invite.py b/addons/mail/wizard/invite.py index 5fddd574182..4d3d34d8116 100644 --- a/addons/mail/wizard/invite.py +++ b/addons/mail/wizard/invite.py @@ -62,10 +62,9 @@ class invite_wizard(osv.osv_memory): # send an email if 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') + 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') diff --git a/addons/portal/mail_mail.py b/addons/portal/mail_mail.py index 5d2a91e691f..751b7d68033 100644 --- a/addons/portal/mail_mail.py +++ b/addons/portal/mail_mail.py @@ -41,7 +41,7 @@ class mail_mail(osv.Model): if partner: contex_signup = dict(context or {}, signup_valid=True) partner = partner_obj.browse(cr, SUPERUSER_ID, partner.id, context=contex_signup) - text = _("""

Access your messages and personal documents through our Customer Portal

""") % partner.signup_url + text = _("""Access your messages and personal documents through our Customer Portal""") % 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 +49,8 @@ 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 = _("""

Access this document directly in OpenERP

""") % url + text = _("""Access this document directly in OpenERP""") % url except except_orm, e: pass - body = append_content_to_html(body, ("

%s

" % text), plaintext=False) + body = append_content_to_html(body, text, plaintext=False, container_tag='div') return body From ed7e0919f193f0b55e3bc10c009bc9745ccce951 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Fri, 25 Jan 2013 14:34:26 +0100 Subject: [PATCH 005/146] [IMP] res_user: change view form bzr revid: chm@openerp.com-20130125133426-o2yblxrrp7ambjzd --- addons/mail/res_users_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mail/res_users_view.xml b/addons/mail/res_users_view.xml index a119765e1ec..f49ff72194a 100644 --- a/addons/mail/res_users_view.xml +++ b/addons/mail/res_users_view.xml @@ -23,7 +23,7 @@ - + From c2beeab40b5e187f59672c910753ffe8d0ae2c34 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Mon, 28 Jan 2013 15:02:01 +0100 Subject: [PATCH 006/146] [IMP] crm, project: context with simple_mode for the user_id field bzr revid: chm@openerp.com-20130128140201-pdy1xdkqxh0a3in4 --- addons/crm/crm_lead_view.xml | 4 ++-- addons/project/project_view.xml | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 3d7bd45a209..e0e8cdc5028 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -152,7 +152,7 @@ --> - + diff --git a/addons/email_template/email_template.py b/addons/email_template/email_template.py index 743384059b4..6778f8cf752 100644 --- a/addons/email_template/email_template.py +++ b/addons/email_template/email_template.py @@ -143,7 +143,9 @@ class email_template(osv.osv): 'subject': fields.char('Subject', translate=True, help="Subject (placeholders may be used here)",), 'email_from': fields.char('From', help="Sender address (placeholders may be used here)"), 'email_to': fields.char('To (Emails)', help="Comma-separated recipient addresses (placeholders may be used here)"), - 'email_recipients': fields.char('To (Partners)', help="Comma-separated ids of recipient partners (placeholders may be used here)"), + 'partner_to': fields.char('To (Partners)', + help="Comma-separated ids of recipient partners (placeholders may be used here)", + oldname='email_recipients'), 'email_cc': fields.char('Cc', help="Carbon copy recipients (placeholders may be used here)"), 'reply_to': fields.char('Reply-To', help="Preferred response address (placeholders may be used here)"), 'mail_server_id': fields.many2one('ir.mail_server', 'Outgoing Mail Server', readonly=False, @@ -311,7 +313,7 @@ class email_template(osv.osv): template = self.get_email_template(cr, uid, template_id, res_id, context) values = {} for field in ['subject', 'body_html', 'email_from', - 'email_to', 'email_recipients', 'email_cc', 'reply_to']: + 'email_to', 'partner_to', 'email_cc', 'reply_to']: values[field] = self.render_template(cr, uid, getattr(template, field), template.model, res_id, context=context) \ or False @@ -371,7 +373,7 @@ class email_template(osv.osv): values = self.generate_email(cr, uid, template_id, res_id, context=context) assert 'email_from' in values, 'email_from is missing or empty after template rendering, send_mail() cannot proceed' attachments = values.pop('attachments') or {} - del values['email_recipients'] # TODO Properly use them. + del values['partner_to'] # TODO Properly use them. msg_id = mail_mail.create(cr, uid, values, context=context) # link attachments attachment_ids = [] diff --git a/addons/email_template/email_template_view.xml b/addons/email_template/email_template_view.xml index 4cddb31c8e1..5e1d7b931da 100644 --- a/addons/email_template/email_template_view.xml +++ b/addons/email_template/email_template_view.xml @@ -30,7 +30,7 @@ - + @@ -78,7 +78,7 @@ - + diff --git a/addons/email_template/tests/test_mail.py b/addons/email_template/tests/test_mail.py index b87b6d63000..c3ee385cf11 100644 --- a/addons/email_template/tests/test_mail.py +++ b/addons/email_template/tests/test_mail.py @@ -170,20 +170,20 @@ class test_message_compose(TestMailBase): self.assertEqual(set(message_bird_pids), set(partner_ids), 'mail.message on bird notified_partner_ids incorrect') # ---------------------------------------- - # CASE4: test newly introduced email_recipients field + # CASE4: test newly introduced partner_to field # ---------------------------------------- # get already-created partners back p_b_id = self.res_partner.search(cr, uid, [('email', '=', 'b@b.b')])[0] p_c_id = self.res_partner.search(cr, uid, [('email', '=', 'c@c.c')])[0] p_d_id = self.res_partner.search(cr, uid, [('email', '=', 'd@d.d')])[0] - # modify template: use email_recipients, use template and email address in email_to to test all features together + # modify template: use partner_to, use template and email address in email_to to test all features together user_model_id = self.registry('ir.model').search(cr, uid, [('model', '=', 'res.users')])[0] email_template.write(cr, uid, [email_template_id], { 'model_id': user_model_id, 'body_html': '${object.login}', 'email_to': '${object.email} c@c', - 'email_recipients': '%i,%i' % (p_b_id, p_c_id), + 'partner_to': '%i,%i' % (p_b_id, p_c_id), 'email_cc': 'd@d', }) # patner by email + partner by id (no double) diff --git a/addons/email_template/wizard/email_template_preview_view.xml b/addons/email_template/wizard/email_template_preview_view.xml index 8dd4bc92ba7..2d7abcb4eef 100644 --- a/addons/email_template/wizard/email_template_preview_view.xml +++ b/addons/email_template/wizard/email_template_preview_view.xml @@ -17,7 +17,7 @@ - + diff --git a/addons/email_template/wizard/mail_compose_message.py b/addons/email_template/wizard/mail_compose_message.py index b39ed4e5639..bc97383bc19 100644 --- a/addons/email_template/wizard/mail_compose_message.py +++ b/addons/email_template/wizard/mail_compose_message.py @@ -65,7 +65,7 @@ class mail_compose_message(osv.TransientModel): """ - mass_mailing: we cannot render, so return the template values - normal mode: return rendered values """ if template_id and composition_mode == 'mass_mail': - values = self.pool.get('email.template').read(cr, uid, template_id, ['subject', 'body_html'], context) + values = self.pool.get('email.template').read(cr, uid, template_id, ['email_from', 'partner_to', 'reply_to', 'subject', 'body_html'], context) values.pop('id') elif template_id: # FIXME odo: change the mail generation to avoid attachment duplication @@ -122,7 +122,7 @@ class mail_compose_message(osv.TransientModel): mail.compose.message, transform email_cc and email_to into partner_ids """ template_values = self.pool.get('email.template').generate_email(cr, uid, template_id, res_id, context=context) # filter template values - fields = ['body_html', 'subject', 'email_to', 'email_recipients', 'email_cc', 'attachments'] + fields = ['body_html', 'subject', 'email_to', 'partner_to', 'email_cc', 'attachments'] values = dict((field, template_values[field]) for field in fields if template_values.get(field)) values['body'] = values.pop('body_html', '') # transform email_to, email_cc into partner_ids @@ -132,9 +132,9 @@ class mail_compose_message(osv.TransientModel): for mail in mails: partner_id = self.pool.get('res.partner').find_or_create(cr, uid, mail, context=context) values['partner_ids'].append(partner_id) - email_recipients = values.pop('email_recipients', '') - if email_recipients: - for partner_id in email_recipients.split(','): + partner_to = values.pop('partner_to', '') + if partner_to: + for partner_id in partner_to.split(','): values['partner_ids'].append(int(partner_id)) values['partner_ids'] = list(set(values['partner_ids'])) diff --git a/addons/portal_sale/portal_sale_data.xml b/addons/portal_sale/portal_sale_data.xml index 31a2f19ef28..2cd7ca8b501 100644 --- a/addons/portal_sale/portal_sale_data.xml +++ b/addons/portal_sale/portal_sale_data.xml @@ -8,7 +8,7 @@ Sales Order - Send by Email (Portal) ${object.user_id.email or ''} ${object.company_id.name} ${object.state in ('draft', 'sent') and 'Quotation' or 'Order'} (Ref ${object.name or 'n/a' }) - ${object.partner_invoice_id.id} + ${object.partner_invoice_id.id} @@ -97,7 +97,7 @@ Invoice - Send by Email (Portal) ${object.user_id.email or object.company_id.email or 'noreply@localhost'} ${object.company_id.name} Invoice (Ref ${object.number or 'n/a' }) - ${object.partner_id.id} + ${object.partner_id.id} diff --git a/addons/purchase/edi/purchase_order_action_data.xml b/addons/purchase/edi/purchase_order_action_data.xml index d616ff1d116..819f7e26b55 100644 --- a/addons/purchase/edi/purchase_order_action_data.xml +++ b/addons/purchase/edi/purchase_order_action_data.xml @@ -21,7 +21,7 @@ Purchase Order - Send by mail ${object.validator.email or ''} ${object.company_id.name} Order (Ref ${object.name or 'n/a' }) - ${object.partner_id.id} + ${object.partner_id.id} diff --git a/addons/sale/edi/sale_order_action_data.xml b/addons/sale/edi/sale_order_action_data.xml index 16712532285..a7f597f4339 100644 --- a/addons/sale/edi/sale_order_action_data.xml +++ b/addons/sale/edi/sale_order_action_data.xml @@ -22,7 +22,7 @@ Sales Order - Send by Email ${object.user_id.email or ''} ${object.company_id.name} ${object.state in ('draft', 'sent') and 'Quotation' or 'Order'} (Ref ${object.name or 'n/a' }) - ${object.partner_invoice_id.id} + ${object.partner_invoice_id.id} From 0aaca4daa92bcaba2a981de11c136689fe80209c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 25 Feb 2013 17:48:57 +0100 Subject: [PATCH 018/146] [IMP] mail: improved mass mailing. Correctly take into account email_to, email_cc, partner_to even if no template. Mass mailing is a no-subtype post with additional recipients manually notified. Added option (in technical features) to send to followers, or to directly create a mail_mail. Added some default values in mail_message. Added explicit management of email_from and reply_to. Having a reply_to bypasses the 'model-res_id' in message_id behavior allowing to construct threads. Added explicit recipient_ids field on mail_mail that replaces the recipient_ids parameter in mail_mail.send(). Updated tests accordingly. bzr revid: tde@openerp.com-20130225164857-i635atksj7riq9nd --- addons/crm/crm_lead_view.xml | 16 ++++++ addons/email_template/email_template_view.xml | 2 +- addons/email_template/tests/test_mail.py | 1 + .../wizard/mail_compose_message.py | 36 +++++++++++-- .../wizard/mail_compose_message_view.xml | 5 ++ addons/mail/mail_followers.py | 36 ++++++------- addons/mail/mail_mail.py | 52 +++++++------------ addons/mail/mail_mail_view.xml | 6 ++- addons/mail/mail_message.py | 16 +++--- addons/mail/mail_thread.py | 3 +- addons/mail/res_partner_view.xml | 3 ++ addons/mail/tests/test_mail_features.py | 4 +- addons/mail/wizard/invite.py | 23 ++++---- addons/mail/wizard/mail_compose_message.py | 35 ++++++++++--- .../mail/wizard/mail_compose_message_view.xml | 33 +++++++----- 15 files changed, 173 insertions(+), 98 deletions(-) diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 87c130547cd..1b961e5a3e0 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -577,5 +577,21 @@ + + + diff --git a/addons/email_template/email_template_view.xml b/addons/email_template/email_template_view.xml index 5e1d7b931da..51e6b53f622 100644 --- a/addons/email_template/email_template_view.xml +++ b/addons/email_template/email_template_view.xml @@ -28,7 +28,7 @@ - + diff --git a/addons/email_template/tests/test_mail.py b/addons/email_template/tests/test_mail.py index c3ee385cf11..56abe6a0fef 100644 --- a/addons/email_template/tests/test_mail.py +++ b/addons/email_template/tests/test_mail.py @@ -130,6 +130,7 @@ class test_message_compose(TestMailBase): # 1. Mass_mail on pigs and bird, with a default_partner_ids set to check he is correctly added context = { 'default_composition_mode': 'mass_mail', + 'default_notify': True, 'default_model': 'mail.group', 'default_res_id': self.group_pigs_id, 'default_template_id': email_template_id, diff --git a/addons/email_template/wizard/mail_compose_message.py b/addons/email_template/wizard/mail_compose_message.py index bc97383bc19..b7da6ccc236 100644 --- a/addons/email_template/wizard/mail_compose_message.py +++ b/addons/email_template/wizard/mail_compose_message.py @@ -22,6 +22,7 @@ from openerp import tools from openerp.osv import osv, fields + def _reopen(self, res_id, model): return {'type': 'ir.actions.act_window', 'view_mode': 'form', @@ -36,6 +37,7 @@ def _reopen(self, res_id, model): }, } + class mail_compose_message(osv.TransientModel): _inherit = 'mail.compose.message' @@ -59,13 +61,25 @@ class mail_compose_message(osv.TransientModel): _columns = { # incredible hack of the day: size=-1 means we want an int db column instead of an str one 'template_id': fields.selection(_get_templates, 'Template', size=-1), + 'partner_to': fields.char('To (Partner IDs)', readonly=True, + help="Comma-separated list of recipient partners ids (placeholders may be used here)"), + 'email_to': fields.char('To (Emails)', readonly=True, + help="Comma-separated recipient addresses (placeholders may be used here)",), + 'email_cc': fields.char('Cc (Emails)', readonly=True, + help="Carbon copy recipients (placeholders may be used here)"), + } + + _defaults = { + 'partner_to': lambda self, cr, uid, ctx={}: '', + 'email_to': lambda self, cr, uid, ctx={}: '', + 'email_cc': lambda self, cr, uid, ctx={}: '', } def onchange_template_id(self, cr, uid, ids, template_id, composition_mode, model, res_id, context=None): """ - mass_mailing: we cannot render, so return the template values - normal mode: return rendered values """ if template_id and composition_mode == 'mass_mail': - values = self.pool.get('email.template').read(cr, uid, template_id, ['email_from', 'partner_to', 'reply_to', 'subject', 'body_html'], context) + values = self.pool.get('email.template').read(cr, uid, template_id, ['subject', 'body_html', 'email_from', 'email_to', 'email_cc', 'partner_to', 'reply_to'], context) values.pop('id') elif template_id: # FIXME odo: change the mail generation to avoid attachment duplication @@ -80,11 +94,11 @@ class mail_compose_message(osv.TransientModel): 'datas_fname': attach_fname, 'res_model': model, 'res_id': res_id, - 'type': 'binary', # override default_type from context, possibly meant for another model! + 'type': 'binary', # override default_type from context, possibly meant for another model! } values['attachment_ids'].append(ir_attach_obj.create(cr, uid, data_attach, context=context)) else: - values = self.default_get(cr, uid, ['body', 'subject', 'partner_ids', 'attachment_ids'], context=context) + values = self.default_get(cr, uid, ['subject', 'body', 'email_from', 'email_to', 'email_cc', 'partner_to', 'reply_to', 'attachment_ids'], context=context) if values.get('body_html'): values['body'] = values.pop('body_html') @@ -122,7 +136,7 @@ class mail_compose_message(osv.TransientModel): mail.compose.message, transform email_cc and email_to into partner_ids """ template_values = self.pool.get('email.template').generate_email(cr, uid, template_id, res_id, context=context) # filter template values - fields = ['body_html', 'subject', 'email_to', 'partner_to', 'email_cc', 'attachments'] + fields = ['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to', 'attachments'] values = dict((field, template_values[field]) for field in fields if template_values.get(field)) values['body'] = values.pop('body_html', '') # transform email_to, email_cc into partner_ids @@ -150,6 +164,20 @@ class mail_compose_message(osv.TransientModel): values = {} # get values to return email_dict = super(mail_compose_message, self).render_message(cr, uid, wizard, res_id, context) + + email_to = self.render_template(cr, uid, wizard.email_to, wizard.model, res_id, context) + email_cc = self.render_template(cr, uid, wizard.email_cc, wizard.model, res_id, context) + partner_to = self.render_template(cr, uid, wizard.partner_to, wizard.model, res_id, context) + email_dict['partner_ids'] = [] + + mails = tools.email_split((email_to or '') + ' ' + (email_cc or '')) + for mail in mails: + partner_id = self.pool.get('res.partner').find_or_create(cr, uid, mail, context=context) + email_dict['partner_ids'].append(partner_id) + if partner_to: + for partner_id in partner_to.split(','): + email_dict['partner_ids'].append(int(partner_id)) + values.update(email_dict) return values diff --git a/addons/email_template/wizard/mail_compose_message_view.xml b/addons/email_template/wizard/mail_compose_message_view.xml index 34a2112e1ac..5b820e5e1ec 100644 --- a/addons/email_template/wizard/mail_compose_message_view.xml +++ b/addons/email_template/wizard/mail_compose_message_view.xml @@ -7,6 +7,11 @@ mail.compose.message + + + + +
Use template diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py index a9d33f4585d..8b0174137b8 100644 --- a/addons/mail/mail_followers.py +++ b/addons/mail/mail_followers.py @@ -75,7 +75,7 @@ class mail_notification(osv.Model): if not cr.fetchone(): cr.execute('CREATE INDEX mail_notification_partner_id_read_starred_message_id ON mail_notification (partner_id, read, starred, message_id)') - def get_partners_to_notify(self, cr, uid, message, context=None): + def get_partners_to_notify(self, cr, uid, message, partners_to_notify=[], context=None): """ Return the list of partners to notify, based on their preferences. :param browse_record message: mail.message to notify @@ -85,6 +85,9 @@ class mail_notification(osv.Model): if notification.read: continue partner = notification.partner_id + # NOtify only required partners + if partner.id not in partners_to_notify: + continue # Do not send to partners without email address defined if not partner.email: continue @@ -100,17 +103,24 @@ class mail_notification(osv.Model): notify_pids.append(partner.id) return notify_pids - def _notify(self, cr, uid, msg_id, context=None): + def _notify(self, cr, uid, msg_id, partners_to_notify=[], context=None): """ Send by email the notification depending on the user preferences """ if context is None: context = {} + if not partners_to_notify: + return True + mail_message_obj = self.pool.get('mail.message') + + # update message + mail_message_obj.write(cr, uid, msg_id, {'notified_partner_ids': [(4, id) for id in partners_to_notify]}, context=context) + # mail_notify_noemail (do not send email) or no partner_ids: do not send, return if context.get('mail_notify_noemail'): return True # browse as SUPERUSER_ID because of access to res_partner not necessarily allowed msg = self.pool.get('mail.message').browse(cr, SUPERUSER_ID, msg_id, context=context) - notify_partner_ids = self.get_partners_to_notify(cr, uid, msg, context=context) - if not notify_partner_ids: + partners_to_notify = self.get_partners_to_notify(cr, uid, msg, partners_to_notify=partners_to_notify, context=context) + if not partners_to_notify: return True # add the context in the email @@ -126,26 +136,16 @@ class mail_notification(osv.Model): if signature: body_html = tools.append_content_to_html(body_html, signature, plaintext=True, 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: - email_from = '%s <%s@%s>' % (msg.author_id.name, msg.author_id.user_ids[0].alias_name, msg.author_id.user_ids[0].alias_domain) - elif msg.author_id: - email_from = '%s <%s>' % (msg.author_id.name, msg.author_id.email) - else: - email_from = msg.email_from - mail_values = { 'mail_message_id': msg.id, - 'email_to': [], 'auto_delete': True, 'body_html': body_html, - 'email_from': email_from, - 'state': 'outgoing', + 'recipient_ids': [(4, id) for id in partners_to_notify] } - mail_values['email_to'] = ', '.join(mail_values['email_to']) + if msg.email_from: + mail_values['email_from'] = msg.email_from 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) + return mail_mail.send(cr, uid, [email_notif_id], context=context) except Exception: return False - diff --git a/addons/mail/mail_mail.py b/addons/mail/mail_mail.py index 1b3ca152a9a..b8509885f19 100644 --- a/addons/mail/mail_mail.py +++ b/addons/mail/mail_mail.py @@ -55,22 +55,25 @@ class mail_mail(osv.Model): help="Permanently delete this email after sending it, to save space"), 'references': fields.text('References', help='Message references, such as identifiers of previous messages', readonly=1), 'email_from': fields.char('From', help='Message sender, taken from user preferences.'), - 'email_to': fields.text('To', help='Message recipients'), + 'email_to': fields.text('To', help='Message recipients (emails)'), + 'recipient_ids': fields.many2many('res.partner', string='Message recipients (partners)'), 'email_cc': fields.char('Cc', help='Carbon copy message recipients'), - 'reply_to': fields.char('Reply-To', help='Preferred response address for the message'), 'body_html': fields.text('Rich-text Contents', help="Rich-text/HTML message"), + # If not set in create values, auto-detected based on create values (res_id, model, email_from) + 'reply_to': fields.char('Reply-To', help='Preferred response address for the message'), + # Auto-detected based on create() - if 'mail_message_id' was passed then this mail is a notification # and during unlink() we will not cascade delete the parent and its attachments 'notification': fields.boolean('Is Notification') } def _get_default_from(self, cr, uid, context=None): - this = self.pool.get('res.users').browse(cr, uid, uid, context=context) + this = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context) if this.alias_domain: - return '%s@%s' % (this.alias_name, this.alias_domain) + return '%s <%s@%s>' % (this.name, this.alias_name, this.alias_domain) elif this.email: - return this.email + return '%s <%s>' % (this.name, this.email) raise osv.except_osv(_('Invalid Action!'), _("Unable to send email, please configure the sender's email address or alias.")) _defaults = { @@ -82,12 +85,16 @@ class mail_mail(osv.Model): # protection for `default_type` values leaking from menu action context (e.g. for invoices) # To remove when automatic context propagation is removed in web client if context and context.get('default_type') and context.get('default_type') not in self._all_columns['type'].column.selection: - context = dict(context, default_type = None) + context = dict(context, default_type=None) return super(mail_mail, self).default_get(cr, uid, fields, context=context) def create(self, cr, uid, values, context=None): if 'notification' not in values and values.get('mail_message_id'): values['notification'] = True + if not values.get('reply_to') and values.get('res_id') and values.get('model') and hasattr(self.pool.get(values.get('model')), 'message_get_reply_to'): + values['reply_to'] = self.pool.get(values.get('model')).message_get_reply_to(cr, uid, [values.get('res_id')], context=context)[0] + elif not values.get('reply_to'): + values['reply_to'] = values.get('email_from', False) return super(mail_mail, self).create(cr, uid, values, context=context) def unlink(self, cr, uid, ids, context=None): @@ -190,22 +197,6 @@ class mail_mail(osv.Model): pass return body - def send_get_mail_reply_to(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 - each notification email a partner receives. - - :param browse_record mail: mail.mail browse_record - :param browse_record partner: specific recipient partner - """ - if mail.reply_to: - return mail.reply_to - if not mail.model or not mail.res_id: - return False - if not hasattr(self.pool.get(mail.model), 'message_get_reply_to'): - return False - return self.pool.get(mail.model).message_get_reply_to(cr, uid, [mail.res_id], context=context)[0] - def send_get_email_dict(self, cr, uid, mail, partner=None, context=None): """ Return a dictionary for specific email values, depending on a partner, or generic to the whole recipients given by mail.email_to. @@ -215,7 +206,6 @@ class mail_mail(osv.Model): """ body = self.send_get_mail_body(cr, uid, mail, partner=partner, context=context) subject = self.send_get_mail_subject(cr, uid, mail, partner=partner, context=context) - reply_to = self.send_get_mail_reply_to(cr, uid, mail, partner=partner, context=context) body_alternative = tools.html2plaintext(body) email_to = [partner.email] if partner else tools.email_split(mail.email_to) return { @@ -223,10 +213,9 @@ class mail_mail(osv.Model): 'body_alternative': body_alternative, 'subject': subject, 'email_to': email_to, - 'reply_to': reply_to, } - def send(self, cr, uid, ids, auto_commit=False, recipient_ids=None, context=None): + def send(self, cr, uid, ids, auto_commit=False, context=None): """ Sends the selected emails immediately, ignoring their current state (mails that have already been sent should not be passed unless they should actually be re-sent). @@ -237,14 +226,10 @@ class mail_mail(osv.Model): :param bool auto_commit: whether to force a commit of the mail status after sending each mail (meant only for scheduler processing); should never be True during normal transactions (default: False) - :param list recipient_ids: specific list of res.partner recipients. - If set, one email is sent to each partner. Its is possible to - tune the sent email through ``send_get_mail_body`` and ``send_get_mail_subject``. - If not specified, one email is sent to mail_mail.email_to. :return: True """ ir_mail_server = self.pool.get('ir.mail_server') - for mail in self.browse(cr, uid, ids, context=context): + for mail in self.browse(cr, SUPERUSER_ID, ids, context=context): try: # handle attachments attachments = [] @@ -252,11 +237,10 @@ class mail_mail(osv.Model): attachments.append((attach.datas_fname, base64.b64decode(attach.datas))) # specific behavior to customize the send email for notified partners email_list = [] - if recipient_ids: - for partner in self.pool.get('res.partner').browse(cr, SUPERUSER_ID, recipient_ids, context=context): - email_list.append(self.send_get_email_dict(cr, uid, mail, partner=partner, context=context)) - else: + if mail.email_to: email_list.append(self.send_get_email_dict(cr, uid, mail, context=context)) + for partner in mail.recipient_ids: + email_list.append(self.send_get_email_dict(cr, uid, mail, partner=partner, context=context)) # build an RFC2822 email.message.Message object and send it without queuing for email in email_list: diff --git a/addons/mail/mail_mail_view.xml b/addons/mail/mail_mail_view.xml index 72d41e33a84..c44b5da5080 100644 --- a/addons/mail/mail_mail_view.xml +++ b/addons/mail/mail_mail_view.xml @@ -25,6 +25,8 @@ + + @@ -67,7 +69,7 @@ - + @@ -97,7 +99,7 @@ - + diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 77573f0d2f8..758203a5794 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -139,6 +139,8 @@ class mail_message(osv.Model): "message, comment for other messages such as user replies"), 'email_from': fields.char('From', help="Email address of the sender. This field is set when no matching partner is found for incoming emails."), + 'reply_to': fields.char('Reply-To', + help='Reply email address. Setting the reply_to bypasses the automatic thread creation.'), 'author_id': fields.many2one('res.partner', 'Author', select=1, ondelete='set null', help="Author of the message. If not set, email_from may hold an email address that did not match any partner."), @@ -185,8 +187,9 @@ class mail_message(osv.Model): _defaults = { 'type': 'email', 'date': lambda *a: fields.datetime.now(), - 'author_id': lambda self, cr, uid, ctx={}: self._get_default_author(cr, uid, ctx), + 'author_id': lambda self, cr, uid, ctx=None: self._get_default_author(cr, uid, ctx), 'body': '', + 'email_from': lambda self, cr, uid, ctx=None: self.pool.get('mail.mail')._get_default_from(cr, uid, ctx), } #------------------------------------------------------ @@ -731,7 +734,10 @@ class mail_message(osv.Model): if context is None: context = {} default_starred = context.pop('default_starred', False) - if not values.get('message_id') and values.get('res_id') and values.get('model'): + # generate message_id, to redirect answers to the right discussion thread + if not values.get('message_id') and values.get('reply_to'): + values['message_id'] = tools.generate_tracking_message_id('reply_to') + elif not values.get('message_id') and values.get('res_id') and values.get('model'): values['message_id'] = tools.generate_tracking_message_id('%(res_id)s-%(model)s' % values) elif not values.get('message_id'): values['message_id'] = tools.generate_tracking_message_id('private') @@ -861,7 +867,7 @@ class mail_message(osv.Model): # message has no subtype_id: pure log message -> no partners, no one notified if not message.subtype_id: return True - + # all followers of the mail.message document have to be added as partners and notified if message.model and message.res_id: fol_obj = self.pool.get("mail.followers") @@ -883,9 +889,7 @@ class mail_message(osv.Model): partners_to_notify |= set(message.partner_ids) # notify - if partners_to_notify: - self.write(cr, SUPERUSER_ID, [newid], {'notified_partner_ids': [(4, p.id) for p in partners_to_notify]}, context=context) - notification_obj._notify(cr, uid, newid, context=context) + notification_obj._notify(cr, uid, newid, partners_to_notify=[p.id for p in partners_to_notify], context=context) message.refresh() # An error appear when a user receive a notification without notifying diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index d53536da8f7..c096293c5b3 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -771,8 +771,7 @@ class mail_thread(osv.AbstractModel): author_ids = self._message_find_partners(cr, uid, message, ['From'], context=context) if author_ids: msg_dict['author_id'] = author_ids[0] - else: - msg_dict['email_from'] = decode(message.get('from')) + msg_dict['email_from'] = decode(message.get('from')) partner_ids = self._message_find_partners(cr, uid, message, ['To', 'Cc'], context=context) msg_dict['partner_ids'] = [(4, partner_id) for partner_id in partner_ids] diff --git a/addons/mail/res_partner_view.xml b/addons/mail/res_partner_view.xml index a4aa56ae971..7df5d27c9d0 100644 --- a/addons/mail/res_partner_view.xml +++ b/addons/mail/res_partner_view.xml @@ -7,6 +7,9 @@ res.partner + + +
diff --git a/addons/mail/tests/test_mail_features.py b/addons/mail/tests/test_mail_features.py index 4302dab8669..a4bcb60c5a6 100644 --- a/addons/mail/tests/test_mail_features.py +++ b/addons/mail/tests/test_mail_features.py @@ -154,7 +154,7 @@ class test_mail(TestMailBase): new_mail = self.mail_message.browse(cr, uid, self.mail_message.search(cr, uid, [('message_id', '=', test_msg_id)])[0]) # Test: author_id set, not email_from self.assertEqual(new_mail.author_id, user_raoul.partner_id, 'message process wrong author found') - self.assertFalse(new_mail.email_from, 'message process should not set the email_from when an author is found') + self.assertEqual(new_mail.email_from, user_raoul.email, 'message process wrong email_from') # Do: post a new message, with a unknown partner test_msg_id = '' @@ -524,7 +524,7 @@ class test_mail(TestMailBase): # 1. mass_mail on pigs and bird compose_id = mail_compose.create(cr, uid, {'subject': _subject, 'body': '${object.description}'}, - {'default_composition_mode': 'mass_mail', 'default_model': 'mail.group', 'default_res_id': False, + {'default_composition_mode': 'mass_mail', 'default_model': 'mail.group', 'default_res_id': False, 'default_notify': True, 'active_ids': [self.group_pigs_id, group_bird_id]}) compose = mail_compose.browse(cr, uid, compose_id) diff --git a/addons/mail/wizard/invite.py b/addons/mail/wizard/invite.py index 72678d468ff..687249a6445 100644 --- a/addons/mail/wizard/invite.py +++ b/addons/mail/wizard/invite.py @@ -66,16 +66,17 @@ class invite_wizard(osv.osv_memory): 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') + # 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], - 'body_html': '%s' % wizard.message, - 'auto_delete': True, - }, context=context) - mail_mail.send(cr, uid, [mail_id], recipient_ids=[follower_id], context=context) + # the invite wizard should create a private message not related to any object -> no model, no res_id + mail_mail = self.pool.get('mail.mail') + 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], + 'body_html': '%s' % wizard.message, + 'auto_delete': True, + 'recipient_ids': [(4, id) for id in new_follower_ids] + }, context=context) + mail_mail.send(cr, uid, [mail_id], context=context) return {'type': 'ir.actions.act_window_close'} diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index ec0c2a8de06..f646b884ad8 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -113,6 +113,12 @@ class mail_compose_message(osv.TransientModel): 'partner_ids': fields.many2many('res.partner', 'mail_compose_message_res_partner_rel', 'wizard_id', 'partner_id', 'Additional contacts'), + 'notify': fields.boolean('Notify followers', + help='Notify followers of the documents.'), + 'post': fields.boolean('Post', + help='Post a copy of the message on the document communication history.'), + 'same_thread': fields.boolean('Reply in the document', + help='Replies to the messages will go into the selected document.'), 'attachment_ids': fields.many2many('ir.attachment', 'mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id', 'Attachments'), @@ -124,6 +130,9 @@ class mail_compose_message(osv.TransientModel): 'body': lambda self, cr, uid, ctx={}: '', 'subject': lambda self, cr, uid, ctx={}: False, 'partner_ids': lambda self, cr, uid, ctx={}: [], + 'notify': lambda self, cr, uid, ctx={}: False, + 'post': lambda self, cr, uid, ctx={}: True, + 'same_thread': lambda self, cr, uid, ctx={}: True, } def _notify(self, cr, uid, newid, context=None): @@ -215,15 +224,27 @@ class mail_compose_message(osv.TransientModel): new_attachments = email_dict.pop('attachments', []) post_values['attachments'] += new_attachments post_values.update(email_dict) + # email_from: mass mailing only can specify another email_from + if email_dict.get('email_from'): + post_values['email_from'] = email_dict.pop('email_from') + # replies redirection: mass mailing only + if not wizard.same_thread: + post_values['reply_to'] = email_dict.pop('reply_to') # automatically subscribe recipients if asked to if context.get('mail_post_autofollow') and wizard.model and post_values.get('partner_ids'): active_model_pool.message_subscribe(cr, uid, [res_id], [item[1] for item in post_values.get('partner_ids')], context=context) # post the message - active_model_pool.message_post(cr, uid, [res_id], type='comment', subtype='mt_comment', context=context, **post_values) - - # post process: update attachments, because id is not necessarily known when adding attachments in Chatter - # self.pool.get('ir.attachment').write(cr, uid, [attach.id for attach in wizard.attachment_ids], { - # 'res_id': wizard.id, 'res_model': wizard.model or False}, context=context) + if mass_mail_mode and not wizard.post: + post_values['recipient_ids'] = post_values.pop('partner_ids') + self.pool.get('mail.mail').create(cr, uid, post_values, context=context) + else: + subtype = False + if wizard.notify: + subtype = 'mail.mt_comment' + msg_id = active_model_pool.message_post(cr, uid, [res_id], type='comment', subtype=subtype, context=context, **post_values) + # mass_mailing, post without notify: notify specific partners + if mass_mail_mode and not wizard.notify and post_values['partner_ids']: + self.pool.get('mail.notification')._notify(cr, uid, msg_id, [item[1] for item in post_values['partner_ids']], context=context) return {'type': 'ir.actions.act_window_close'} @@ -234,6 +255,8 @@ class mail_compose_message(osv.TransientModel): return { 'subject': self.render_template(cr, uid, wizard.subject, wizard.model, res_id, context), 'body': self.render_template(cr, uid, wizard.body, wizard.model, res_id, context), + 'email_from': self.render_template(cr, uid, wizard.email_from, wizard.model, res_id, context), + 'reply_to': self.render_template(cr, uid, wizard.reply_to, wizard.model, res_id, context), } def render_template(self, cr, uid, template, model, res_id, context=None): @@ -258,7 +281,7 @@ class mail_compose_message(osv.TransientModel): result = eval(exp, { 'user': self.pool.get('res.users').browse(cr, uid, uid, context=context), 'object': self.pool.get(model).browse(cr, uid, res_id, context=context), - 'context': dict(context), # copy context to prevent side-effects of eval + 'context': dict(context), # copy context to prevent side-effects of eval }) return result and tools.ustr(result) or '' return template and EXPRESSION_PATTERN.sub(merge, template) diff --git a/addons/mail/wizard/mail_compose_message_view.xml b/addons/mail/wizard/mail_compose_message_view.xml index fca5ec65ca0..29a305a0462 100644 --- a/addons/mail/wizard/mail_compose_message_view.xml +++ b/addons/mail/wizard/mail_compose_message_view.xml @@ -12,25 +12,31 @@ + + -
From 39095efe789383f40648f6d3618f875e4006b757 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Mon, 4 Mar 2013 13:57:02 +0100 Subject: [PATCH 028/146] [IMP] lunch: quick create user with access to lunch, remove help for quick create bzr revid: chm@openerp.com-20130304125702-9hp6jg8q329nokoy --- addons/hr/hr_view.xml | 2 +- addons/lunch/lunch_view.xml | 6 ++---- addons/project/project_view.xml | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/addons/hr/hr_view.xml b/addons/hr/hr_view.xml index e26fe565656..5c2919f902b 100644 --- a/addons/hr/hr_view.xml +++ b/addons/hr/hr_view.xml @@ -51,7 +51,7 @@ + help="Related user name for the resource to manage its access."/> diff --git a/addons/lunch/lunch_view.xml b/addons/lunch/lunch_view.xml index b4b5a1ee313..9325f681ee5 100644 --- a/addons/lunch/lunch_view.xml +++ b/addons/lunch/lunch_view.xml @@ -325,8 +325,7 @@ + context="{'default_groups_ref': ['lunch.group_lunch_user']}"/> @@ -412,8 +411,7 @@ + context="{'default_groups_ref': ['lunch.group_lunch_user']}"/> diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index 8229d59f741..e41caf0fcaa 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -386,8 +386,7 @@ + context="{'default_groups_ref': ['project.group_project_user']}"/> From 2c73e51a545fbc33f737f16b06309bf836a4dd93 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Mar 2013 10:49:56 +0100 Subject: [PATCH 029/146] [IMP] mail_followers: invite message ' invited you to follow document: ' bzr revid: chm@openerp.com-20130305094956-93lf0ttjw02a9omb --- addons/mail/wizard/invite.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/mail/wizard/invite.py b/addons/mail/wizard/invite.py index c22d3262de1..89b64d2a8a8 100644 --- a/addons/mail/wizard/invite.py +++ b/addons/mail/wizard/invite.py @@ -33,8 +33,13 @@ 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'): + user_name = self.pool.get('res.users').name_get(cr, uid, [uid], context=context)[0][1] + ir_model = self.pool.get('ir.model') + model_ids = ir_model.search(cr, uid, [('model', '=', self.pool.get(result.get('res_model'))._name)], context=context) + model_name = ir_model.name_get(cr, uid, model_ids, context=context)[0][1] + document_name = self.pool.get(result.get('res_model')).name_get(cr, uid, [result.get('res_id')], context=context)[0][1] - message = _('
You have been invited to follow %s.
' % document_name) + message = _('
%s invited you to follow %s document: %s.
' % (user_name, model_name, document_name)) result['message'] = message elif 'message' in fields: result['message'] = _('
You have been invited to follow a new document.
') From a57c0797000266d9488e855d59150b245a1bb361 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Mar 2013 11:11:43 +0100 Subject: [PATCH 030/146] [IMP] mail_followers: invite tests bzr revid: chm@openerp.com-20130305101143-6mcydxw60y18kw20 --- addons/mail/tests/test_invite.py | 4 ++-- addons/mail/wizard/invite.py | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/addons/mail/tests/test_invite.py b/addons/mail/tests/test_invite.py index 73221c0746d..aef1456c45f 100644 --- a/addons/mail/tests/test_invite.py +++ b/addons/mail/tests/test_invite.py @@ -42,7 +42,7 @@ class test_invite(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', + self.assertEqual(sent_email.get('subject'), 'Invitation to follow Discussion group document', 'subject of invitation email is incorrect') - self.assertTrue('You have been invited to follow Pigs' in sent_email.get('body'), + self.assertTrue('Raoul Grosbedon invited you to follow Discussion group document: Pigs' in sent_email.get('body'), 'body of invitation email is incorrect') diff --git a/addons/mail/wizard/invite.py b/addons/mail/wizard/invite.py index 89b64d2a8a8..04151c7df5f 100644 --- a/addons/mail/wizard/invite.py +++ b/addons/mail/wizard/invite.py @@ -32,8 +32,8 @@ 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) + user_name = self.pool.get('res.users').name_get(cr, uid, [uid], context=context)[0][1] if 'message' in fields and result.get('res_model') and result.get('res_id'): - user_name = self.pool.get('res.users').name_get(cr, uid, [uid], context=context)[0][1] ir_model = self.pool.get('ir.model') model_ids = ir_model.search(cr, uid, [('model', '=', self.pool.get(result.get('res_model'))._name)], context=context) model_name = ir_model.name_get(cr, uid, model_ids, context=context)[0][1] @@ -42,7 +42,7 @@ class invite_wizard(osv.osv_memory): message = _('
%s invited you to follow %s document: %s.
' % (user_name, model_name, document_name)) result['message'] = message elif 'message' in fields: - result['message'] = _('
You have been invited to follow a new document.
') + result['message'] = _('
%s invited you to follow a new document.
' % user_name) return result _columns = { @@ -65,6 +65,10 @@ 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) + ir_model = self.pool.get('ir.model') + model_ids = ir_model.search(cr, uid, [('model', '=', self.pool.get(result.get('res_model'))._name)], context=context) + model_name = ir_model.name_get(cr, uid, model_ids, context=context)[0][1] + # send an email if wizard.send_mail and wizard.message: # add signature @@ -78,7 +82,7 @@ class invite_wizard(osv.osv_memory): 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 document' % model_name, 'body_html': '%s' % wizard.message, 'auto_delete': True, }, context=context) From a6f2191dc6f3802dd667dbd361ced9be1d2a2e99 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Mar 2013 11:26:44 +0100 Subject: [PATCH 031/146] [FIX] mail_followers: invite tests bzr revid: chm@openerp.com-20130305102644-3goqo24diirjoq0z --- addons/mail/wizard/invite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mail/wizard/invite.py b/addons/mail/wizard/invite.py index 04151c7df5f..b8e44983a57 100644 --- a/addons/mail/wizard/invite.py +++ b/addons/mail/wizard/invite.py @@ -66,7 +66,7 @@ class invite_wizard(osv.osv_memory): model_obj.message_subscribe(cr, uid, [wizard.res_id], new_follower_ids, context=context) ir_model = self.pool.get('ir.model') - model_ids = ir_model.search(cr, uid, [('model', '=', self.pool.get(result.get('res_model'))._name)], context=context) + 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 From f7484297d9c947933dfd82314f0b406bdbc67bdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 5 Mar 2013 13:42:59 +0100 Subject: [PATCH 032/146] [CLEAN] mail.compose.message: some cleaning in new fields strings, and in form vivew. bzr revid: tde@openerp.com-20130305124259-x3vb5ds2xi9v389d --- .../wizard/mail_compose_message_view.xml | 2 +- addons/mail/wizard/mail_compose_message.py | 8 ++++---- addons/mail/wizard/mail_compose_message_view.xml | 15 ++++++++------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/addons/email_template/wizard/mail_compose_message_view.xml b/addons/email_template/wizard/mail_compose_message_view.xml index 5b820e5e1ec..8391924532b 100644 --- a/addons/email_template/wizard/mail_compose_message_view.xml +++ b/addons/email_template/wizard/mail_compose_message_view.xml @@ -7,7 +7,7 @@ mail.compose.message - + diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 8445da3e40a..9a84e1b31fc 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -113,11 +113,11 @@ class mail_compose_message(osv.TransientModel): 'partner_ids': fields.many2many('res.partner', 'mail_compose_message_res_partner_rel', 'wizard_id', 'partner_id', 'Additional contacts'), - 'notify': fields.boolean('Notify followers', - help='Notify followers of the documents.'), - 'post': fields.boolean('Post', + 'post': fields.boolean('Post a copy in the document', help='Post a copy of the message on the document communication history.'), - 'same_thread': fields.boolean('Reply in the document', + 'notify': fields.boolean('Notify followers', + help='Notify followers of the document'), + 'same_thread': fields.boolean('Replies in the document', help='Replies to the messages will go into the selected document.'), 'attachment_ids': fields.many2many('ir.attachment', 'mail_compose_message_ir_attachments_rel', diff --git a/addons/mail/wizard/mail_compose_message_view.xml b/addons/mail/wizard/mail_compose_message_view.xml index 29a305a0462..6c85e6b17f1 100644 --- a/addons/mail/wizard/mail_compose_message_view.xml +++ b/addons/mail/wizard/mail_compose_message_view.xml @@ -12,11 +12,17 @@ - - + + + + +
From aaf7949b4269586e5a4b4f499b478e2947f742f1 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Mar 2013 14:02:28 +0100 Subject: [PATCH 033/146] [FIX] portal: mail_fallowers invite bzr revid: chm@openerp.com-20130305130228-0ebmc26lbd9s6c4t --- addons/portal/tests/test_portal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/portal/tests/test_portal.py b/addons/portal/tests/test_portal.py index 7cbb1c28012..a7b064997d7 100644 --- a/addons/portal/tests/test_portal.py +++ b/addons/portal/tests/test_portal.py @@ -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', + self.assertEqual(sent_email.get('subject'), 'Invitation to follow Discussion group document', 'subject of invitation email is incorrect') - self.assertTrue('You have been invited to follow Pigs' in sent_email.get('body'), + self.assertTrue('Administrator invited you to follow Discussion group document: Pigs' in sent_email.get('body'), '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') From 68fbf7cf44d3310573ee7f7026d1c49e8233a72f Mon Sep 17 00:00:00 2001 From: Chris Biersbach Date: Tue, 5 Mar 2013 14:14:55 +0100 Subject: [PATCH 034/146] [FIX] PoS: Fixes a small, context=None related bug in the pos box wizard bzr revid: cbi@openerp.com-20130305131455-5jsn089777xy5dnx --- addons/point_of_sale/wizard/pos_box.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/addons/point_of_sale/wizard/pos_box.py b/addons/point_of_sale/wizard/pos_box.py index 14e653b915c..776d962a3a8 100644 --- a/addons/point_of_sale/wizard/pos_box.py +++ b/addons/point_of_sale/wizard/pos_box.py @@ -31,6 +31,10 @@ class PosBoxIn(PosBox): _inherit = 'cash.box.in' def _compute_values_for_statement_line(self, cr, uid, box, record, context=None): + + if context is None: + context = {} + values = super(PosBoxIn, self)._compute_values_for_statement_line(cr, uid, box, record, context=context) active_model = context.get('active_model', False) or False From 787305a6ce8f62155392e00f0c07865233caaaca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 5 Mar 2013 16:13:12 +0100 Subject: [PATCH 035/146] [IMP] mail: notifications: handle opt-out parameter. bzr revid: tde@openerp.com-20130305151312-xkylrhhlsf6l44yj --- addons/mail/mail_followers.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py index 8b0174137b8..750b06bf595 100644 --- a/addons/mail/mail_followers.py +++ b/addons/mail/mail_followers.py @@ -80,6 +80,7 @@ class mail_notification(osv.Model): :param browse_record message: mail.message to notify """ + has_opt_out = self.pool.get('res.partner')._all_columns.get('opt_out') notify_pids = [] for notification in message.notification_ids: if notification.read: @@ -91,8 +92,8 @@ class mail_notification(osv.Model): # Do not send to partners without email address defined if not partner.email: continue - # Partner does not want to receive any emails - if partner.notification_email_send == 'none': + # Partner does not want to receive any emails or is opt-out + if partner.notification_email_send == 'none' or (has_opt_out and partner.opt_out): continue # Partner wants to receive only emails and comments if partner.notification_email_send == 'comment' and message.type not in ('email', 'comment'): @@ -119,7 +120,9 @@ class mail_notification(osv.Model): return True # browse as SUPERUSER_ID because of access to res_partner not necessarily allowed msg = self.pool.get('mail.message').browse(cr, SUPERUSER_ID, msg_id, context=context) + print 'before partner_to_notify', partners_to_notify partners_to_notify = self.get_partners_to_notify(cr, uid, msg, partners_to_notify=partners_to_notify, context=context) + print 'partner_to_notify', partners_to_notify if not partners_to_notify: return True @@ -144,6 +147,8 @@ class mail_notification(osv.Model): } if msg.email_from: mail_values['email_from'] = msg.email_from + if msg.reply_to: + mail_values['reply_to'] = msg.reply_to email_notif_id = mail_mail.create(cr, uid, mail_values, context=context) try: return mail_mail.send(cr, uid, [email_notif_id], context=context) From 9d2dba4ea7856bbe39cbeacfe63bd284474f2e71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 5 Mar 2013 16:13:32 +0100 Subject: [PATCH 036/146] [IMP] mail_thread: handle use_email_to when managing incoming emails. bzr revid: tde@openerp.com-20130305151332-q6bcr91gk51ugk9v --- addons/mail/mail_thread.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index ac4a1b8ae9c..2a5d2e2a4fd 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -468,6 +468,8 @@ class mail_thread(osv.AbstractModel): # 1. Verify if this is a reply to an existing thread thread_references = references or in_reply_to ref_match = thread_references and tools.reference_re.search(thread_references) + use_email_to = thread_references and tools.use_email_to_re.search(thread_references) + if ref_match: thread_id = int(ref_match.group(1)) model = ref_match.group(2) or model @@ -479,7 +481,7 @@ class mail_thread(osv.AbstractModel): return [(model, thread_id, custom_values, uid)] # Verify whether this is a reply to a private message - if in_reply_to: + if in_reply_to and not use_email_to: message_ids = self.pool.get('mail.message').search(cr, uid, [('message_id', '=', in_reply_to)], limit=1, context=context) if message_ids: message = self.pool.get('mail.message').browse(cr, uid, message_ids[0], context=context) From 8b105c3e56b0b4f9679ce1f14c0f7b74844122ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 5 Mar 2013 16:14:08 +0100 Subject: [PATCH 037/146] [FIX] mail.compose.message: fixed notify field, not showing when it should. bzr revid: tde@openerp.com-20130305151408-h6800swy10xnu634 --- addons/mail/wizard/mail_compose_message_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mail/wizard/mail_compose_message_view.xml b/addons/mail/wizard/mail_compose_message_view.xml index 6c85e6b17f1..2812287a860 100644 --- a/addons/mail/wizard/mail_compose_message_view.xml +++ b/addons/mail/wizard/mail_compose_message_view.xml @@ -18,7 +18,7 @@ + attrs="{'invisible':[('post', '!=', True)]}"/> Date: Wed, 6 Mar 2013 15:31:25 +0100 Subject: [PATCH 040/146] [REM] mail: removed opt-out management. bzr revid: tde@openerp.com-20130306143125-4p4zretkzjpv0jn8 --- addons/mail/mail_followers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py index 750b06bf595..a065a70be56 100644 --- a/addons/mail/mail_followers.py +++ b/addons/mail/mail_followers.py @@ -80,7 +80,6 @@ class mail_notification(osv.Model): :param browse_record message: mail.message to notify """ - has_opt_out = self.pool.get('res.partner')._all_columns.get('opt_out') notify_pids = [] for notification in message.notification_ids: if notification.read: @@ -93,7 +92,7 @@ class mail_notification(osv.Model): if not partner.email: continue # Partner does not want to receive any emails or is opt-out - if partner.notification_email_send == 'none' or (has_opt_out and partner.opt_out): + if partner.notification_email_send == 'none': continue # Partner wants to receive only emails and comments if partner.notification_email_send == 'comment' and message.type not in ('email', 'comment'): From 3e3818ddc0b1ab4c0a60e0f0ecfc2ce456ecc77c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 6 Mar 2013 16:06:59 +0100 Subject: [PATCH 041/146] =?UTF-8?q?[IMP]=20partner,=20lead:=20added=20not?= =?UTF-8?q?=20opt-out=20filter=20in=20search=20views.=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bzr revid: tde@openerp.com-20130306150659-jonircm2s7wmwoku --- addons/crm/crm_lead_view.xml | 2 ++ addons/crm/res_partner_view.xml | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 1b961e5a3e0..3a8fcf8e0d6 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -339,6 +339,8 @@ + diff --git a/addons/crm/res_partner_view.xml b/addons/crm/res_partner_view.xml index 00a071fa954..9e7fee82555 100644 --- a/addons/crm/res_partner_view.xml +++ b/addons/crm/res_partner_view.xml @@ -15,6 +15,18 @@ + + res.partner.select.crm + res.partner + + + + + + + + Meetings From 80674364689bc4544df9355dc50213a6bb9755c1 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Thu, 7 Mar 2013 09:25:10 +0100 Subject: [PATCH 042/146] [FIX] Discount should only appear on sales order if it is checked in the settings. bzr revid: jco@openerp.com-20130307082510-mckayx175qu9ispo --- addons/sale/report/sale_order.py | 11 ++++++++++- addons/sale/report/sale_order.rml | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/addons/sale/report/sale_order.py b/addons/sale/report/sale_order.py index b4f0b1589aa..e66a9021276 100644 --- a/addons/sale/report/sale_order.py +++ b/addons/sale/report/sale_order.py @@ -27,9 +27,18 @@ class order(report_sxw.rml_parse): def __init__(self, cr, uid, name, context=None): super(order, self).__init__(cr, uid, name, context=context) self.localcontext.update({ - 'time': time, + 'time': time, + 'show_discount':self._show_discount, }) + def _show_discount(self, uid, context=None): + cr = self.cr + try: + group_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sale', 'group_discount_per_so_line')[1] + except: + return False + return group_id in [x.id for x in self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id] + report_sxw.report_sxw('report.sale.order', 'sale.order', 'addons/sale/report/sale_order.rml', parser=order, header="external") # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale/report/sale_order.rml b/addons/sale/report/sale_order.rml index a00d2d4e3ef..1798ee1d301 100644 --- a/addons/sale/report/sale_order.rml +++ b/addons/sale/report/sale_order.rml @@ -251,7 +251,7 @@ Unit Price - Disc.(%) + [[show_discount(user.id) and "Disc.(%)" or '']] Price @@ -275,7 +275,7 @@ [[ formatLang(line.price_unit , digits=get_digits(dp='Product Price'))]] - [[ formatLang(line.discount, digits=get_digits(dp='Discount'))]] + [[show_discount(user.id) and formatLang(line.discount, digits=get_digits(dp='Discount')) or '']] [[ formatLang(line.price_subtotal, digits=get_digits(dp='Account'), currency_obj=o.pricelist_id.currency_id) ]] From 937bc0ba4a3306572b111c322be7a383422d1138 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Thu, 7 Mar 2013 11:50:31 +0100 Subject: [PATCH 043/146] [FIX] portal_project_long_term: access right and rules bzr revid: chm@openerp.com-20130307105031-d9t7vh642z6bxul7 --- addons/portal_project_long_term/__init__.py | 20 +++++++++ .../portal_project_long_term/__openerp__.py | 42 +++++++++++++++++++ .../security/ir.model.access.csv | 2 + .../security/portal_security.xml | 17 ++++++++ 4 files changed, 81 insertions(+) create mode 100644 addons/portal_project_long_term/__init__.py create mode 100644 addons/portal_project_long_term/__openerp__.py create mode 100644 addons/portal_project_long_term/security/ir.model.access.csv create mode 100644 addons/portal_project_long_term/security/portal_security.xml diff --git a/addons/portal_project_long_term/__init__.py b/addons/portal_project_long_term/__init__.py new file mode 100644 index 00000000000..c8d82ed19bd --- /dev/null +++ b/addons/portal_project_long_term/__init__.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2010-Today OpenERP S.A. (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## diff --git a/addons/portal_project_long_term/__openerp__.py b/addons/portal_project_long_term/__openerp__.py new file mode 100644 index 00000000000..373ae8535dc --- /dev/null +++ b/addons/portal_project_long_term/__openerp__.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2010-Today OpenERP S.A. (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +{ + 'name': 'Portal Issue', + 'version': '0.1', + 'category': 'Tools', + 'complexity': 'easy', + 'description': """ +This module adds issue menu and features to your portal if project_long_term and portal are installed. +====================================================================================================== + """, + 'author': 'OpenERP SA', + 'depends': ['project_long_term', 'portal'], + 'data': [ + 'security/portal_security.xml', + 'security/ir.model.access.csv', + ], + 'installable': True, + 'auto_install': True, + 'category': 'Hidden', +} +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/portal_project_long_term/security/ir.model.access.csv b/addons/portal_project_long_term/security/ir.model.access.csv new file mode 100644 index 00000000000..738c264a71c --- /dev/null +++ b/addons/portal_project_long_term/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_issues,project_phase,project_long_term.model_project_phase,portal.group_portal,1,0,0,0 diff --git a/addons/portal_project_long_term/security/portal_security.xml b/addons/portal_project_long_term/security/portal_security.xml new file mode 100644 index 00000000000..b46d277e4ee --- /dev/null +++ b/addons/portal_project_long_term/security/portal_security.xml @@ -0,0 +1,17 @@ + + + + + + Portal Personal Long term project + + ['|',('project_id.message_follower_ids','in', [user.partner_id.id]),('task_ids.message_follower_ids','in', [user.partner_id.id])] + + + + + + + + + From 12e1e6ad795e5af4835302f25de114abe6f607dc Mon Sep 17 00:00:00 2001 From: Chris Biersbach Date: Tue, 12 Mar 2013 13:24:28 +0100 Subject: [PATCH 044/146] [IMP] Project Issue: Replaces the old message_ids based detection of new messages by an override of mail_thread message_post. The date of last action will be updated to the current date on each message_post call. bzr revid: cbi@openerp.com-20130312122428-9s21kgtac8u3lyaf --- addons/project_issue/project_issue.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index 9233a95634c..eab505443c3 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -393,7 +393,7 @@ class project_issue(base_stage, osv.osv): def write(self, cr, uid, ids, vals, context=None): #Update last action date every time the user change the stage, the state or send a new email - logged_fields = ['stage_id', 'state', 'message_ids'] + logged_fields = ['stage_id', 'state'] if any([field in vals for field in logged_fields]): vals['date_action_last'] = time.strftime('%Y-%m-%d %H:%M:%S') @@ -545,6 +545,14 @@ class project_issue(base_stage, osv.osv): return super(project_issue, self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context) + def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification', subtype=None, parent_id=False, attachments=None, context=None, content_subtype='html', **kwargs): + """ Overrides mail_thread message_post so that we can set the date of last action field when + a new message is posted on the issue. + """ + if thread_id: + self.write(cr, uid, thread_id, {'date_action_last': time.strftime('%Y-%m-%d %H:%M:%S')}, context=context) + + return super(project_issue, self).message_post(cr, uid, thread_id, body=body, subject=subject, type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=context, content_subtype=content_subtype, **kwargs) class project(osv.osv): _inherit = "project.project" From 99063b421f99966c7960e493dff32a24e3e2143c Mon Sep 17 00:00:00 2001 From: Thibault Delavallee Date: Tue, 12 Mar 2013 14:30:29 +0100 Subject: [PATCH 045/146] [REV] mail_thread: message_process: reverted reply_to mechanism, now based on the reply_to-model contained in message_id. bzr revid: tde@openerp.com-20130312133029-67g69s3ttscwhtoc --- addons/mail/mail_message.py | 2 +- addons/mail/mail_thread.py | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 758203a5794..00b0cdc3654 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -736,7 +736,7 @@ class mail_message(osv.Model): default_starred = context.pop('default_starred', False) # generate message_id, to redirect answers to the right discussion thread if not values.get('message_id') and values.get('reply_to'): - values['message_id'] = tools.generate_tracking_message_id('reply_to') + values['message_id'] = tools.generate_tracking_message_id('reply_to-%(model)s' % values) elif not values.get('message_id') and values.get('res_id') and values.get('model'): values['message_id'] = tools.generate_tracking_message_id('%(res_id)s-%(model)s' % values) elif not values.get('message_id'): diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 2a5d2e2a4fd..87caf1df254 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -468,7 +468,6 @@ class mail_thread(osv.AbstractModel): # 1. Verify if this is a reply to an existing thread thread_references = references or in_reply_to ref_match = thread_references and tools.reference_re.search(thread_references) - use_email_to = thread_references and tools.use_email_to_re.search(thread_references) if ref_match: thread_id = int(ref_match.group(1)) @@ -481,8 +480,11 @@ class mail_thread(osv.AbstractModel): return [(model, thread_id, custom_values, uid)] # Verify whether this is a reply to a private message - if in_reply_to and not use_email_to: - message_ids = self.pool.get('mail.message').search(cr, uid, [('message_id', '=', in_reply_to)], limit=1, context=context) + if in_reply_to: + message_ids = self.pool.get('mail.message').search(cr, uid, [ + ('message_id', '=', in_reply_to), + '!', ('message_id', 'ilike', 'reply_to') + ], limit=1, context=context) if message_ids: message = self.pool.get('mail.message').browse(cr, uid, message_ids[0], context=context) _logger.debug('Routing mail with Message-Id %s: direct reply to a private message: %s, custom_values: %s, uid: %s', From d7e5763dcb444a5cda4c9466e87efc7bb9aa19bf Mon Sep 17 00:00:00 2001 From: Thibault Delavallee Date: Tue, 12 Mar 2013 14:38:17 +0100 Subject: [PATCH 046/146] [IMP] mail, email_template: improved mass mailing action (renamed, now using a well defined template) + improved form view of mail.compose.message wizard. bzr revid: tde@openerp.com-20130312133817-y9xztv6gs4ut7ndj --- addons/email_template/res_partner_view.xml | 30 +++++++++++++++++++ .../wizard/mail_compose_message_view.xml | 9 ++++-- addons/mail/wizard/mail_compose_message.py | 1 + .../mail/wizard/mail_compose_message_view.xml | 13 ++++---- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/addons/email_template/res_partner_view.xml b/addons/email_template/res_partner_view.xml index 3d17120d69e..d3bab9d23e6 100644 --- a/addons/email_template/res_partner_view.xml +++ b/addons/email_template/res_partner_view.xml @@ -11,5 +11,35 @@
+ + + + Partner Mass Mail + + + ${object.id} + + + + + + + + + diff --git a/addons/email_template/wizard/mail_compose_message_view.xml b/addons/email_template/wizard/mail_compose_message_view.xml index 8391924532b..f5ad47e20bc 100644 --- a/addons/email_template/wizard/mail_compose_message_view.xml +++ b/addons/email_template/wizard/mail_compose_message_view.xml @@ -8,9 +8,12 @@ - - - + /> + /> + /> diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 9a84e1b31fc..57daaf15a5e 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -127,6 +127,7 @@ class mail_compose_message(osv.TransientModel): _defaults = { 'composition_mode': 'comment', + 'email_from': lambda self, cr, uid, ctx={}: self.pool.get('mail.mail')._get_default_from(cr, uid, context=ctx), 'body': lambda self, cr, uid, ctx={}: '', 'subject': lambda self, cr, uid, ctx={}: False, 'partner_ids': lambda self, cr, uid, ctx={}: [], diff --git a/addons/mail/wizard/mail_compose_message_view.xml b/addons/mail/wizard/mail_compose_message_view.xml index 2812287a860..01cecd7d52c 100644 --- a/addons/mail/wizard/mail_compose_message_view.xml +++ b/addons/mail/wizard/mail_compose_message_view.xml @@ -16,12 +16,14 @@ - + - + attrs="{'invisible':['|', ('post', '!=', True), ('composition_mode', '!=', 'mass_mail')]}"/> + @@ -58,7 +60,7 @@ - + From 360642e53e37c1698d99ee8580faf915f03f5e83 Mon Sep 17 00:00:00 2001 From: Thibault Delavallee Date: Tue, 12 Mar 2013 14:38:47 +0100 Subject: [PATCH 047/146] [IMP] crm: improved mass mailign on lead and opportunities, now linked to a template that handles everything. bzr revid: tde@openerp.com-20130312133847-3csbpz123q8kqs5b --- addons/crm/crm_data.xml | 15 --------------- addons/crm/crm_lead_data.xml | 14 +++++++++++++- addons/crm/crm_lead_view.xml | 10 +++++++++- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/addons/crm/crm_data.xml b/addons/crm/crm_data.xml index e53d8e73599..3db7a457dfd 100644 --- a/addons/crm/crm_data.xml +++ b/addons/crm/crm_data.xml @@ -72,19 +72,4 @@ - - - - - - Opportunity - Send Emails - ${object.name} - - - ${object.partner_id.id} - - - diff --git a/addons/crm/crm_lead_data.xml b/addons/crm/crm_lead_data.xml index 724ec491efe..93290c9a1fa 100644 --- a/addons/crm/crm_lead_data.xml +++ b/addons/crm/crm_lead_data.xml @@ -1,6 +1,7 @@ - + + @@ -221,5 +222,16 @@ section_id + + + Lead/Opportunity Mass Mail + + + ${object.partner_id and object.partner_id.id} + ${! object.partner_id and object.email} + + + diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 3a8fcf8e0d6..1d659bd9cd7 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -582,7 +582,7 @@ - + + + + + From f6c9e78f1f872fb064b1a648f0c8936fa7017484 Mon Sep 17 00:00:00 2001 From: Chris Biersbach Date: Tue, 12 Mar 2013 14:41:38 +0100 Subject: [PATCH 048/146] [IMP] Introduces correct handling of the thread_mpdel context value bzr revid: cbi@openerp.com-20130312134138-7krmnobtlbhud5d2 --- addons/project_issue/project_issue.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index eab505443c3..42158f68539 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -392,10 +392,10 @@ class project_issue(base_stage, osv.osv): context=context) def write(self, cr, uid, ids, vals, context=None): - #Update last action date every time the user change the stage, the state or send a new email + #Update last action date every time the user change the stage or the state logged_fields = ['stage_id', 'state'] if any([field in vals for field in logged_fields]): - vals['date_action_last'] = time.strftime('%Y-%m-%d %H:%M:%S') + vals['date_action_last'] = time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT) return super(project_issue, self).write(cr, uid, ids, vals, context) @@ -550,7 +550,12 @@ class project_issue(base_stage, osv.osv): a new message is posted on the issue. """ if thread_id: - self.write(cr, uid, thread_id, {'date_action_last': time.strftime('%Y-%m-%d %H:%M:%S')}, context=context) + model = context.get('thread_model', self._name) + if model != self._name: + ctx = context.copy() + del ctx['thread_model'] + return self.pool.get(model).message_post(cr, uid, thread_id, body=body, subject=subject, type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=ctx, content_subtype=content_subtype, **kwargs) + self.write(cr, uid, thread_id, {'date_action_last': time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)}, context=context) return super(project_issue, self).message_post(cr, uid, thread_id, body=body, subject=subject, type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=context, content_subtype=content_subtype, **kwargs) From 5773d310e912dfe0657fbc134007167daeda47f2 Mon Sep 17 00:00:00 2001 From: Thibault Delavallee Date: Tue, 12 Mar 2013 15:22:57 +0100 Subject: [PATCH 049/146] [FIX] mail: notification: do not send a notification email to partners having the same email address than the author, because of loops it may cause. bzr revid: tde@openerp.com-20130312142257-sbtv2f3u9lobj6w5 --- addons/mail/mail_followers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py index ecdd39874e3..5d2a8966bb8 100644 --- a/addons/mail/mail_followers.py +++ b/addons/mail/mail_followers.py @@ -93,6 +93,9 @@ class mail_notification(osv.Model): # Do not send to partners without email address defined if not partner.email: continue + # Do not send to partners having same email address than the author (can cause loops or bounce effect due to messy database) + if message.author_id and message.author_id.email == partner.email: + continue # Partner does not want to receive any emails or is opt-out if partner.notification_email_send == 'none': continue From a30a3a0e33b6a6ab2785f01b79728504c290127b Mon Sep 17 00:00:00 2001 From: Chris Biersbach Date: Tue, 12 Mar 2013 16:07:19 +0100 Subject: [PATCH 050/146] [FIX] Stupid, forgot to test for None context again bzr revid: cbi@openerp.com-20130312150719-s6l0d6173cqrmnoe --- addons/project_issue/project_issue.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index 42158f68539..8128f272b00 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -549,6 +549,9 @@ class project_issue(base_stage, osv.osv): """ Overrides mail_thread message_post so that we can set the date of last action field when a new message is posted on the issue. """ + if context is None: + context = {} + if thread_id: model = context.get('thread_model', self._name) if model != self._name: From 1e731875515eca09e658a8f71f1a3bed306e2fb7 Mon Sep 17 00:00:00 2001 From: Chris Biersbach Date: Tue, 12 Mar 2013 16:22:33 +0100 Subject: [PATCH 051/146] [IMP] Project Issue: Correctly updates date_open and date_closed when the corresponding state changes happen. bzr revid: cbi@openerp.com-20130312152233-ejvae8h9wzablf6l --- addons/project_issue/project_issue.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index 8128f272b00..93840dc3821 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -392,10 +392,18 @@ class project_issue(base_stage, osv.osv): context=context) def write(self, cr, uid, ids, vals, context=None): - #Update last action date every time the user change the stage or the state - logged_fields = ['stage_id', 'state'] - if any([field in vals for field in logged_fields]): + + #Update last action date every time the user changes the stage + if 'stage_id' in vals: vals['date_action_last'] = time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT) + state = self.pool.get('project.task.type').read(cr, uid, vals['stage_id'], ['state'], context=context)['state'] + for issue in self.browse(cr, uid, ids, context=context): + # Change from draft to not draft EXCEPT cancelled: The issue has been opened -> set the opening date + if issue.state == 'draft' and state not in ('draft', 'cancelled'): + vals['date_open'] = time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT) + # Change from not done to done: The issue has been closed -> set the closing date + if issue.state != 'done' and state == 'done': + vals['date_closed'] = time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT) return super(project_issue, self).write(cr, uid, ids, vals, context) From 31d218cc67bb2bb8d60b7b0340c3fad5e0614a79 Mon Sep 17 00:00:00 2001 From: Chris Biersbach Date: Wed, 13 Mar 2013 09:38:08 +0100 Subject: [PATCH 052/146] [IMP] Project issue: Improved handling of thread_model context value in message_post. Replaced a read by a browse in Project issue write bzr revid: cbi@openerp.com-20130313083808-o75djyctnj5sgngx --- addons/mail/mail_thread.py | 3 +++ addons/project_issue/project_issue.py | 13 ++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index af21109b89e..4ce99be190c 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -925,6 +925,9 @@ class mail_thread(osv.AbstractModel): model = False if thread_id: model = context.get('thread_model', self._name) if self._name == 'mail.thread' else self._name + if model != self._name: + del context['thread_model'] + return self.pool.get(model).message_post(cr, uid, thread_id, body=body, subject=subject, type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=ctx, content_subtype=content_subtype, **kwargs) # 1: Handle content subtype: if plaintext, converto into HTML if content_subtype == 'plaintext': diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index 93840dc3821..88feee529c2 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -396,7 +396,7 @@ class project_issue(base_stage, osv.osv): #Update last action date every time the user changes the stage if 'stage_id' in vals: vals['date_action_last'] = time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT) - state = self.pool.get('project.task.type').read(cr, uid, vals['stage_id'], ['state'], context=context)['state'] + state = self.pool.get('project.task.type').browse(cr, uid, vals['stage_id'], context=context).state for issue in self.browse(cr, uid, ids, context=context): # Change from draft to not draft EXCEPT cancelled: The issue has been opened -> set the opening date if issue.state == 'draft' and state not in ('draft', 'cancelled'): @@ -560,15 +560,14 @@ class project_issue(base_stage, osv.osv): if context is None: context = {} + res = super(project_issue, self).message_post(cr, uid, thread_id, body=body, subject=subject, type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=context, content_subtype=content_subtype, **kwargs) + if thread_id: model = context.get('thread_model', self._name) - if model != self._name: - ctx = context.copy() - del ctx['thread_model'] - return self.pool.get(model).message_post(cr, uid, thread_id, body=body, subject=subject, type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=ctx, content_subtype=content_subtype, **kwargs) - self.write(cr, uid, thread_id, {'date_action_last': time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)}, context=context) + if model == self._name: + self.write(cr, uid, thread_id, {'date_action_last': time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)}, context=context) - return super(project_issue, self).message_post(cr, uid, thread_id, body=body, subject=subject, type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=context, content_subtype=content_subtype, **kwargs) + return res class project(osv.osv): _inherit = "project.project" From f67b033b31df083b17d1a854cebb84569a5c945e Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 13 Mar 2013 16:59:56 +0100 Subject: [PATCH 053/146] [IMP] quick create for user: default_groups_ref remove help message bzr revid: chm@openerp.com-20130313155956-hqk6dd9fw4qiwsj2 --- addons/hr/hr_view.xml | 3 +-- addons/hr_timesheet/hr_timesheet_view.xml | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/addons/hr/hr_view.xml b/addons/hr/hr_view.xml index 5c2919f902b..e0c3edfdb39 100644 --- a/addons/hr/hr_view.xml +++ b/addons/hr/hr_view.xml @@ -50,8 +50,7 @@ + context="{'default_groups_ref': ['base.group_user']}"/> diff --git a/addons/hr_timesheet/hr_timesheet_view.xml b/addons/hr_timesheet/hr_timesheet_view.xml index 4e97c50431d..5435ba45182 100644 --- a/addons/hr_timesheet/hr_timesheet_view.xml +++ b/addons/hr_timesheet/hr_timesheet_view.xml @@ -31,8 +31,7 @@ + context="{'default_groups_ref': ['base.group_user']}"/> From 07559b253a83f7cd2e0b017e9207691601b41079 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 13 Mar 2013 17:03:10 +0100 Subject: [PATCH 054/146] [IMP] mail_followers: add a comment for get_signature_footer bzr revid: chm@openerp.com-20130313160310-pgckns8w6gb7cqus --- addons/mail/mail_followers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py index a63c35bef8c..afdef5269bf 100644 --- a/addons/mail/mail_followers.py +++ b/addons/mail/mail_followers.py @@ -103,6 +103,9 @@ class mail_notification(osv.Model): return notify_pids def get_signature_footer(self, cr, uid, user_id=None, res_model=None, res_id=None, context=None): + """ Return the footer with signature + On bottom of the message, add the user's company link or the user name and a link to oepenerp + """ footer = "" company = None user = None From 46893a182a40600cebb85fca8e1ad73c5b99f5a4 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 13 Mar 2013 17:05:01 +0100 Subject: [PATCH 055/146] [IMP] mail_followers: remove print in tests bzr revid: chm@openerp.com-20130313160501-ywkyblx39cma9jln --- addons/mail/tests/test_mail_features.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/addons/mail/tests/test_mail_features.py b/addons/mail/tests/test_mail_features.py index 3931dfa0282..3d1ccdd34e4 100644 --- a/addons/mail/tests/test_mail_features.py +++ b/addons/mail/tests/test_mail_features.py @@ -343,9 +343,6 @@ class test_mail(TestMailBase): self._init_mock_build_email() msg1_id = self.mail_group.message_post(cr, user_raoul.id, self.group_pigs_id, body=_body1, subject=_subject, type='comment', subtype='mt_comment') message1 = self.mail_message.browse(cr, uid, msg1_id) - - print "####", msg1_id, "####", message1.body, "####" - sent_emails = self._build_email_kwargs_list # Test: mail.mail notifications have been deleted self.assertFalse(self.mail_mail.search(cr, uid, [('mail_message_id', '=', msg1_id)]), 'mail.mail notifications should have been auto-deleted!') From d80d18ff1b54295c4e48ed70910567cb19231c62 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 13 Mar 2013 17:15:10 +0100 Subject: [PATCH 056/146] [IMP] mail_followers: fix invite button, hidden subtype if only one bzr revid: chm@openerp.com-20130313161510-kkis63zaoc3yb6kz --- addons/mail/static/src/css/mail.css | 2 -- addons/mail/static/src/js/mail_followers.js | 6 +++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index aeb9e5e55cd..5dd0b828a48 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -548,8 +548,6 @@ .openerp .oe_followers button.oe_invite{ margin: 5px 0; padding: 2px 8px; - position: relative; - top: -2px; font-size: 12px; text-shadow: none; width: 100% diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index bd5c52f18ba..fba5eefc110 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -217,13 +217,17 @@ openerp_mail_followers = function(session, mail) { /** Display subtypes: {'name': default, followed} */ display_subtypes:function (data, id) { var self = this; - this.$('.oe_subtype_list').empty(); + 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(); + } }, do_follow: function () { From 31d8417539247c5048b593ac1dc8f3b4fbbf6d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 14 Mar 2013 10:06:23 +0100 Subject: [PATCH 057/146] [CLEAN] removed commented noupdate that was present to ease debugging. bzr revid: tde@openerp.com-20130314090623-z9q3zp2n68yvpght --- addons/crm/crm_lead_data.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/crm/crm_lead_data.xml b/addons/crm/crm_lead_data.xml index 93290c9a1fa..3623dce3977 100644 --- a/addons/crm/crm_lead_data.xml +++ b/addons/crm/crm_lead_data.xml @@ -1,7 +1,6 @@ - - + From 2ca8ff41c351e162a7e406f1c8b5b774aed68579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 14 Mar 2013 12:02:23 +0100 Subject: [PATCH 058/146] [CLEAN] mail_followers: removed print statements. bzr revid: tde@openerp.com-20130314110223-18torul5eoih6m5e --- addons/mail/mail_followers.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py index a065a70be56..61b21f78876 100644 --- a/addons/mail/mail_followers.py +++ b/addons/mail/mail_followers.py @@ -119,9 +119,7 @@ class mail_notification(osv.Model): return True # browse as SUPERUSER_ID because of access to res_partner not necessarily allowed msg = self.pool.get('mail.message').browse(cr, SUPERUSER_ID, msg_id, context=context) - print 'before partner_to_notify', partners_to_notify partners_to_notify = self.get_partners_to_notify(cr, uid, msg, partners_to_notify=partners_to_notify, context=context) - print 'partner_to_notify', partners_to_notify if not partners_to_notify: return True From 4ae0b6845258cd1b599430bc53b4b051a309d08d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 14 Mar 2013 12:02:39 +0100 Subject: [PATCH 059/146] [IMP] crm: improved template and comments. bzr revid: tde@openerp.com-20130314110239-1k1c8jrbax94gp8m --- addons/crm/crm_lead_data.xml | 7 ++++--- addons/crm/crm_lead_view.xml | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/addons/crm/crm_lead_data.xml b/addons/crm/crm_lead_data.xml index 3623dce3977..1607e69799a 100644 --- a/addons/crm/crm_lead_data.xml +++ b/addons/crm/crm_lead_data.xml @@ -221,14 +221,15 @@ section_id - + Lead/Opportunity Mass Mail ${object.partner_id and object.partner_id.id} - ${! object.partner_id and object.email} + ${not object.partner_id and object.email_from} diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 1d659bd9cd7..8f40ca2b1a5 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -597,8 +597,8 @@ 'default_template_id': ref('crm.lead_template'), }"/> - + From f4dbf7051b4326b169cc1b94fc3b3ffd112b0640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 14 Mar 2013 12:03:15 +0100 Subject: [PATCH 060/146] [FIX] email_template: fixed behavior of email_to, email_cc, partner_to; improved form view. bzr revid: tde@openerp.com-20130314110315-3gfl7mjj08jgqo93 --- .../wizard/mail_compose_message.py | 20 +++++++++---------- .../wizard/mail_compose_message_view.xml | 20 +++++++++++++------ 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/addons/email_template/wizard/mail_compose_message.py b/addons/email_template/wizard/mail_compose_message.py index ba8ac737866..05b73eeb276 100644 --- a/addons/email_template/wizard/mail_compose_message.py +++ b/addons/email_template/wizard/mail_compose_message.py @@ -61,11 +61,11 @@ class mail_compose_message(osv.TransientModel): _columns = { # incredible hack of the day: size=-1 means we want an int db column instead of an str one 'template_id': fields.selection(_get_templates, 'Template', size=-1), - 'partner_to': fields.char('To (Partner IDs)', readonly=True, + 'partner_to': fields.char('To (Partner IDs)', help="Comma-separated list of recipient partners ids (placeholders may be used here)"), - 'email_to': fields.char('To (Emails)', readonly=True, + 'email_to': fields.char('To (Emails)', help="Comma-separated recipient addresses (placeholders may be used here)",), - 'email_cc': fields.char('Cc (Emails)', readonly=True, + 'email_cc': fields.char('Cc (Emails)', help="Carbon copy recipients (placeholders may be used here)"), } @@ -79,8 +79,9 @@ class mail_compose_message(osv.TransientModel): """ - mass_mailing: we cannot render, so return the template values - normal mode: return rendered values """ if template_id and composition_mode == 'mass_mail': - values = self.pool.get('email.template').read(cr, uid, template_id, ['subject', 'body_html', 'email_from', 'email_to', 'email_cc', 'partner_to', 'reply_to'], context) - values.pop('id') + fields = ['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to'] + template_values = self.pool.get('email.template').read(cr, uid, template_id, fields, context) + values = dict((field, template_values[field]) for field in fields if template_values.get(field)) elif template_id: # FIXME odo: change the mail generation to avoid attachment duplication values = self.generate_email_for_composer(cr, uid, template_id, res_id, context=context) @@ -165,11 +166,10 @@ class mail_compose_message(osv.TransientModel): values = {} # get values to return email_dict = super(mail_compose_message, self).render_message(cr, uid, wizard, res_id, context) - email_dict['email_to'] = self.render_template(cr, uid, wizard.email_to, wizard.model, res_id, context) - email_dict['email_cc'] = self.render_template(cr, uid, wizard.email_cc, wizard.model, res_id, context) - email_dict['partner_to'] = self.render_template(cr, uid, wizard.partner_to, wizard.model, res_id, context) - # transform email_to, email_cc into partner_ids - email_dict['partner_ids'] = self._get_or_create_partners_from_values(cr, uid, email_dict, context=context) + # those values are not managed; they are readonly + email_dict.pop('email_to', None) + email_dict.pop('email_cc', None) + email_dict.pop('partner_to', None) # update template values by wizard values values.update(email_dict) return values diff --git a/addons/email_template/wizard/mail_compose_message_view.xml b/addons/email_template/wizard/mail_compose_message_view.xml index f5ad47e20bc..1b2be68a4a2 100644 --- a/addons/email_template/wizard/mail_compose_message_view.xml +++ b/addons/email_template/wizard/mail_compose_message_view.xml @@ -8,12 +8,20 @@ - /> - /> - /> + From 8a95e1886ebdb92916b37cd5a0ff4d5cd2fc7ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 14 Mar 2013 12:03:44 +0100 Subject: [PATCH 061/146] [FIX] mail_compose_message: remove some keys from the context, as they conflict with mail_mail values. bzr revid: tde@openerp.com-20130314110344-w5ashhs3jc1oslzp --- addons/mail/wizard/mail_compose_message.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 57daaf15a5e..12c26c14732 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -234,6 +234,10 @@ class mail_compose_message(osv.TransientModel): # automatically subscribe recipients if asked to if context.get('mail_post_autofollow') and wizard.model and post_values.get('partner_ids'): active_model_pool.message_subscribe(cr, uid, [res_id], [item[1] for item in post_values.get('partner_ids')], context=context) + # clean the context (hint: mass mailing sets some default values that + # could be wrongly interpreted by mail_mail) + context.pop('default_email_to', None) + context.pop('default_partner_ids', None) # post the message if mass_mail_mode and not wizard.post: post_values['recipient_ids'] = post_values.pop('partner_ids') From 8ba623dd8e80a5229e17acd299c0c4772203727c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 14 Mar 2013 13:06:11 +0100 Subject: [PATCH 062/146] [CLEAN] mail_mail: cleaned a bit the form view bzr revid: tde@openerp.com-20130314120611-p9fouks0wk0e10do --- addons/mail/mail_mail.py | 2 +- addons/mail/mail_mail_view.xml | 34 +++++++++++++--------------------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/addons/mail/mail_mail.py b/addons/mail/mail_mail.py index 050081e97d3..484a7175d94 100644 --- a/addons/mail/mail_mail.py +++ b/addons/mail/mail_mail.py @@ -56,7 +56,7 @@ class mail_mail(osv.Model): 'references': fields.text('References', help='Message references, such as identifiers of previous messages', readonly=1), 'email_from': fields.char('From', help='Message sender, taken from user preferences.'), 'email_to': fields.text('To', help='Message recipients (emails)'), - 'recipient_ids': fields.many2many('res.partner', string='Message recipients (partners)'), + 'recipient_ids': fields.many2many('res.partner', string='To (Partners)'), 'email_cc': fields.char('Cc', help='Carbon copy message recipients'), 'body_html': fields.text('Rich-text Contents', help="Rich-text/HTML message"), diff --git a/addons/mail/mail_mail_view.xml b/addons/mail/mail_mail_view.xml index c44b5da5080..30091dae22c 100644 --- a/addons/mail/mail_mail_view.xml +++ b/addons/mail/mail_mail_view.xml @@ -14,33 +14,23 @@
- - - - - - - - - - - - - - - - - - - - + + + + + + + + + + - + @@ -48,6 +38,8 @@ + + From a147b69404090401fcb2e6b97e3a899b06151ab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 14 Mar 2013 17:21:41 +0100 Subject: [PATCH 063/146] [IMP] addons: add default employee group on default_groups_ref. bzr revid: tde@openerp.com-20130314162141-skfq5w98zhpn31yh --- addons/crm/crm_lead_view.xml | 4 ++-- addons/hr/hr_view.xml | 2 +- addons/hr_recruitment/hr_recruitment_view.xml | 2 +- addons/hr_timesheet/hr_timesheet_view.xml | 4 ++-- addons/lunch/lunch_view.xml | 4 ++-- addons/product/product_view.xml | 2 +- addons/project/project_view.xml | 4 ++-- addons/project_issue/project_issue_view.xml | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 2b29a2582d9..c257faa001e 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -152,7 +152,7 @@
+ context="{'default_groups_ref': ['base.group_user', 'base.group_sale_salesman_all_leads']}"/>