diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py
index 776111613ec..2a9dd559fb4 100644
--- a/addons/account/account_move_line.py
+++ b/addons/account/account_move_line.py
@@ -1038,6 +1038,8 @@ class account_move_line(osv.osv):
all_moves = list(set(all_moves) - set(move_ids))
if unlink_ids:
if opening_reconciliation:
+ raise osv.except_osv(_('Warning!'),
+ _('Opening Entries have already been generated. Please run "Cancel Closing Entries" wizard to cancel those entries and then run this wizard.'))
obj_move_rec.write(cr, uid, unlink_ids, {'opening_reconciliation': False})
obj_move_rec.unlink(cr, uid, unlink_ids)
if len(all_moves) >= 2:
diff --git a/addons/crm/crm_phonecall.py b/addons/crm/crm_phonecall.py
index 382102710bb..b983dbfd4b3 100644
--- a/addons/crm/crm_phonecall.py
+++ b/addons/crm/crm_phonecall.py
@@ -141,6 +141,7 @@ class crm_phonecall(osv.osv):
'partner_phone' : call.partner_phone,
'partner_mobile' : call.partner_mobile,
'priority': call.priority,
+ 'opportunity_id': call.opportunity_id and call.opportunity_id.id or False,
}
new_id = self.create(cr, uid, vals, context=context)
if action == 'log':
diff --git a/addons/delivery/delivery.py b/addons/delivery/delivery.py
index 33db829ac80..0281c2787fb 100644
--- a/addons/delivery/delivery.py
+++ b/addons/delivery/delivery.py
@@ -19,11 +19,14 @@
#
##############################################################################
+import logging
import time
from openerp.osv import fields,osv
from openerp.tools.translate import _
import openerp.addons.decimal_precision as dp
+_logger = logging.getLogger(__name__)
+
class delivery_carrier(osv.osv):
_name = "delivery.carrier"
_description = "Carrier"
@@ -51,14 +54,24 @@ class delivery_carrier(osv.osv):
for carrier in self.browse(cr, uid, ids, context=context):
order_id=context.get('order_id',False)
price=False
+ available = False
if order_id:
order = sale_obj.browse(cr, uid, order_id, context=context)
carrier_grid=self.grid_get(cr,uid,[carrier.id],order.partner_shipping_id.id,context)
if carrier_grid:
- price=grid_obj.get_price(cr, uid, carrier_grid, order, time.strftime('%Y-%m-%d'), context)
+ try:
+ price=grid_obj.get_price(cr, uid, carrier_grid, order, time.strftime('%Y-%m-%d'), context)
+ available = True
+ except osv.except_osv, e:
+ # no suitable delivery method found, probably configuration error
+ _logger.error("Carrier %s: %s\n%s" % (carrier.name, e.name, e.value))
+ price = 0.0
else:
price = 0.0
- res[carrier.id]=price
+ res[carrier.id] = {
+ 'price': price,
+ 'available': available
+ }
return res
_columns = {
@@ -66,7 +79,9 @@ class delivery_carrier(osv.osv):
'partner_id': fields.many2one('res.partner', 'Transport Company', required=True, help="The partner that is doing the delivery service."),
'product_id': fields.many2one('product.product', 'Delivery Product', required=True),
'grids_id': fields.one2many('delivery.grid', 'carrier_id', 'Delivery Grids'),
- 'price' : fields.function(get_price, string='Price'),
+ 'available' : fields.function(get_price, string='Available',type='boolean', multi='price',
+ help="Is the carrier method possible with the current order."),
+ 'price' : fields.function(get_price, string='Price', multi='price'),
'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the delivery carrier without removing it."),
'normal_price': fields.float('Normal Price', help="Keep empty if the pricing depends on the advanced pricing per destination"),
'free_if_more_than': fields.boolean('Free If Order Total Amount Is More Than', help="If the order is more expensive than a certain amount, the customer can benefit from a free shipping"),
diff --git a/addons/hr_attendance/hr_attendance.py b/addons/hr_attendance/hr_attendance.py
index a7950fef8d0..4887d41a52c 100644
--- a/addons/hr_attendance/hr_attendance.py
+++ b/addons/hr_attendance/hr_attendance.py
@@ -61,13 +61,16 @@ class hr_attendance(osv.osv):
('employee_id', '=', obj.employee_id.id),
('name', '<', obj.name), ('action', '=', 'sign_in')
], limit=1, order='name DESC')
- last_signin = self.browse(cr, uid, last_signin_id, context=context)[0]
+ if last_signin_id:
+ last_signin = self.browse(cr, uid, last_signin_id, context=context)[0]
- # Compute time elapsed between sign-in and sign-out
- last_signin_datetime = datetime.strptime(last_signin.name, '%Y-%m-%d %H:%M:%S')
- signout_datetime = datetime.strptime(obj.name, '%Y-%m-%d %H:%M:%S')
- workedhours_datetime = (signout_datetime - last_signin_datetime)
- res[obj.id] = ((workedhours_datetime.seconds) / 60) / 60
+ # Compute time elapsed between sign-in and sign-out
+ last_signin_datetime = datetime.strptime(last_signin.name, '%Y-%m-%d %H:%M:%S')
+ signout_datetime = datetime.strptime(obj.name, '%Y-%m-%d %H:%M:%S')
+ workedhours_datetime = (signout_datetime - last_signin_datetime)
+ res[obj.id] = ((workedhours_datetime.seconds) / 60) / 60
+ else:
+ res[obj.id] = False
return res
_columns = {
diff --git a/addons/hr_payroll/hr_payroll.py b/addons/hr_payroll/hr_payroll.py
index 4dea994a130..397938f3442 100644
--- a/addons/hr_payroll/hr_payroll.py
+++ b/addons/hr_payroll/hr_payroll.py
@@ -368,7 +368,7 @@ class hr_payslip(osv.osv):
#OR if it starts between the given dates
clause_2 = ['&',('date_start', '<=', date_to),('date_start','>=', date_from)]
#OR if it starts before the date_from and finish after the date_end (or never finish)
- clause_3 = [('date_start','<=', date_from),'|',('date_end', '=', False),('date_end','>=', date_to)]
+ clause_3 = ['&',('date_start','<=', date_from),'|',('date_end', '=', False),('date_end','>=', date_to)]
clause_final = [('employee_id', '=', employee.id),'|','|'] + clause_1 + clause_2 + clause_3
contract_ids = contract_obj.search(cr, uid, clause_final, context=context)
return contract_ids
diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py
index a005eb7ea82..aeb0a2b10ec 100644
--- a/addons/mail/mail_followers.py
+++ b/addons/mail/mail_followers.py
@@ -149,10 +149,11 @@ class mail_notification(osv.Model):
company = "%s" % (website_url, user.company_id.name)
else:
company = user.company_id.name
- sent_by = _('Sent from %(company)s using %(openerp)s')
+ sent_by = _('Sent by %(company)s using %(odoo)s.')
+
signature_company = '%s' % (sent_by % {
'company': company,
- 'openerp': "Odoo"
+ 'odoo': "Odoo"
})
footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag='div')
@@ -185,8 +186,9 @@ class mail_notification(osv.Model):
# compute email body (signature, company data)
body_html = message.body
- user_id = message.author_id and message.author_id.user_ids and message.author_id.user_ids[0] and message.author_id.user_ids[0].id or None
- if user_signature:
+ # add user signature except for mail groups, where users are usually adding their own signatures already
+ if user_signature and message.model != 'mail.group':
+ user_id = message.author_id and message.author_id.user_ids and message.author_id.user_ids[0] and message.author_id.user_ids[0].id or None
signature_company = self.get_signature_footer(cr, uid, user_id, res_model=message.model, res_id=message.res_id, context=context)
body_html = tools.append_content_to_html(body_html, signature_company, plaintext=False, container_tag='div')
diff --git a/addons/mail/mail_group.py b/addons/mail/mail_group.py
index 721593d4d76..a654a7b194b 100644
--- a/addons/mail/mail_group.py
+++ b/addons/mail/mail_group.py
@@ -226,8 +226,15 @@ class mail_group(osv.Model):
except Exception:
headers = {}
headers['Precedence'] = 'list'
+ # avoid out-of-office replies from MS Exchange
+ # http://blogs.technet.com/b/exchange/archive/2006/10/06/3395024.aspx
+ headers['X-Auto-Response-Suppress'] = 'OOF'
if group.alias_domain and group.alias_name:
headers['List-Id'] = '%s.%s' % (group.alias_name, group.alias_domain)
headers['List-Post'] = '' % (group.alias_name, group.alias_domain)
+ # Avoid users thinking it was a personal message
+ # X-Forge-To: will replace To: after SMTP envelope is determined by ir.mail.server
+ list_to = '"%s" <%s@%s>' % (group.name, group.alias_name, group.alias_domain)
+ headers['X-Forge-To'] = list_to
res['headers'] = '%s' % headers
return res
diff --git a/addons/mail/tests/test_mail_features.py b/addons/mail/tests/test_mail_features.py
index fdd87bbcfab..84e0d4252b1 100644
--- a/addons/mail/tests/test_mail_features.py
+++ b/addons/mail/tests/test_mail_features.py
@@ -467,14 +467,10 @@ class test_mail(TestMail):
'message_post: notification email subject incorrect')
self.assertIn(_body1, sent_email['body'],
'message_post: notification email body incorrect')
- self.assertIn(user_raoul.signature, sent_email['body'],
- 'message_post: notification email body should contain the sender signature')
self.assertIn('Pigs rules', sent_email['body_alternative'],
'message_post: notification email body alternative should contain the body')
self.assertNotIn('
', sent_email['body_alternative'],
'message_post: notification email body alternative still contains html')
- self.assertIn(html2plaintext(user_raoul.signature), sent_email['body_alternative'],
- 'message_post: notification email body alternative should contain the sender signature')
self.assertFalse(sent_email['references'],
'message_post: references should be False when sending a message that is not a reply')
@@ -538,14 +534,10 @@ class test_mail(TestMail):
'message_post: notification email subject incorrect')
self.assertIn(html_sanitize(_body2), sent_email['body'],
'message_post: notification email does not contain the body')
- self.assertIn(user_raoul.signature, sent_email['body'],
- 'message_post: notification email body should contain the sender signature')
self.assertIn('Pigs rocks', sent_email['body_alternative'],
'message_post: notification email body alternative should contain the body')
self.assertNotIn('
', sent_email['body_alternative'],
'message_post: notification email body alternative still contains html')
- self.assertIn(html2plaintext(user_raoul.signature), sent_email['body_alternative'],
- 'message_post: notification email body alternative should contain the sender signature')
self.assertIn(msg_message_id, sent_email['references'],
'message_post: notification email references lacks parent message message_id')
# Test: attachments + download
diff --git a/addons/procurement/wizard/schedulers_all.py b/addons/procurement/wizard/schedulers_all.py
index 47f4dac440b..5d05291c546 100644
--- a/addons/procurement/wizard/schedulers_all.py
+++ b/addons/procurement/wizard/schedulers_all.py
@@ -19,11 +19,15 @@
#
##############################################################################
+import logging
import threading
+from openerp import tools
from openerp.osv import osv
from openerp.api import Environment
+_logger = logging.getLogger(__name__)
+
class procurement_compute_all(osv.osv_memory):
_name = 'procurement.order.compute.all'
_description = 'Compute all schedulers'
@@ -39,8 +43,17 @@ class procurement_compute_all(osv.osv_memory):
with Environment.manage():
proc_obj = self.pool.get('procurement.order')
#As this function is in a new thread, i need to open a new cursor, because the old one may be closed
-
+
new_cr = self.pool.cursor()
+ # Avoid to run the scheduler multiple times in the same time
+ try:
+ with tools.mute_logger('openerp.sql_db'):
+ new_cr.execute("SELECT id FROM ir_cron WHERE id = %s FOR UPDATE NOWAIT", (scheduler_cron_id,))
+ except Exception:
+ _logger.info('Attempt to run procurement scheduler aborted, as already running')
+ new_cr.rollback()
+ new_cr.close()
+ return {}
user = self.pool.get('res.users').browse(new_cr, uid, uid, context=context)
comps = [x.id for x in user.company_ids]
for comp in comps:
diff --git a/addons/product/product.py b/addons/product/product.py
index 32b3a0bfbf1..96ce4586b59 100644
--- a/addons/product/product.py
+++ b/addons/product/product.py
@@ -395,6 +395,7 @@ class product_attribute_price(osv.osv):
class product_attribute_line(osv.osv):
_name = "product.attribute.line"
+ _rec_name = 'attribute_id'
_columns = {
'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True, ondelete='cascade'),
'attribute_id': fields.many2one('product.attribute', 'Attribute', required=True, ondelete='restrict'),
diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml
index e48c2e61d97..5823f2cab05 100644
--- a/addons/project/project_view.xml
+++ b/addons/project/project_view.xml
@@ -391,7 +391,7 @@
-
+
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index b85716b1aff..44f87b7ab03 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -632,7 +632,7 @@ class sale_order(osv.osv):
compose_form_id = ir_model_data.get_object_reference(cr, uid, 'mail', 'email_compose_message_wizard_form')[1]
except ValueError:
compose_form_id = False
- ctx = dict(context)
+ ctx = dict()
ctx.update({
'default_model': 'sale.order',
'default_res_id': ids[0],
diff --git a/addons/sale/wizard/sale_make_invoice_advance.py b/addons/sale/wizard/sale_make_invoice_advance.py
index c3f1d6cade4..3d8cc3e6997 100644
--- a/addons/sale/wizard/sale_make_invoice_advance.py
+++ b/addons/sale/wizard/sale_make_invoice_advance.py
@@ -37,6 +37,7 @@ class sale_advance_payment_inv(osv.osv_memory):
Use Some Order Lines to invoice a selection of the sales order lines."""),
'qtty': fields.float('Quantity', digits=(16, 2), required=True),
'product_id': fields.many2one('product.product', 'Advance Product',
+ domain=[('type', '=', 'service')],
help="""Select a product of type service which is called 'Advance Product'.
You may have to create it and set it as a default value on this field."""),
'amount': fields.float('Advance Amount', digits_compute= dp.get_precision('Account'),
diff --git a/addons/sale_service/views/sale_service_view.xml b/addons/sale_service/views/sale_service_view.xml
index 0865d95fa0e..59d018ad146 100644
--- a/addons/sale_service/views/sale_service_view.xml
+++ b/addons/sale_service/views/sale_service_view.xml
@@ -16,7 +16,7 @@
product.template
-
+
diff --git a/addons/website_crm/controllers/main.py b/addons/website_crm/controllers/main.py
index b209c70d962..5e2d8e75866 100644
--- a/addons/website_crm/controllers/main.py
+++ b/addons/website_crm/controllers/main.py
@@ -25,6 +25,10 @@ class contactus(http.Controller):
values.update(kwargs=kwargs.items())
return request.website.render("website.contactus", values)
+ def create_lead(self, request, values):
+ """ Allow to be overrided """
+ return request.registry['crm.lead'].create(request.cr, SUPERUSER_ID, values, request.context)
+
@http.route(['/crm/contactus'], type='http', auth="public", website=True)
def contactus(self, **kwargs):
def dict_to_str(title, dictvar):
@@ -41,12 +45,10 @@ class contactus(http.Controller):
post_description = [] # Info to add after the message
values = {}
- lead_model = request.registry['crm.lead']
-
for field_name, field_value in kwargs.items():
if hasattr(field_value, 'filename'):
post_file.append(field_value)
- elif field_name in lead_model._all_columns and field_name not in _BLACKLIST:
+ elif field_name in request.registry['crm.lead']._all_columns and field_name not in _BLACKLIST:
values[field_name] = field_value
elif field_name not in _TECHNICAL: # allow to add some free fields or blacklisted field like ID
post_description.append("%s: %s" % (field_name, field_value))
@@ -80,7 +82,7 @@ class contactus(http.Controller):
post_description.append("%s: %s" % ("REFERER", environ.get("HTTP_REFERER")))
values['description'] += dict_to_str(_("Environ Fields: "), post_description)
- lead_id = lead_model.create(request.cr, SUPERUSER_ID, dict(values, user_id=False), request.context)
+ lead_id = self.create_lead(request, dict(values, user_id=False))
if lead_id:
for field_value in post_file:
attachment_value = {
diff --git a/addons/website_forum/controllers/main.py b/addons/website_forum/controllers/main.py
index 2d2e5f24606..78d69de971b 100644
--- a/addons/website_forum/controllers/main.py
+++ b/addons/website_forum/controllers/main.py
@@ -62,7 +62,7 @@ class WebsiteForum(http.Controller):
forum_id = request.registry['forum.forum'].create(request.cr, request.uid, {
'name': forum_name,
}, context=request.context)
- return request.redirect("/forum/%s" % slug(forum_id))
+ return request.redirect("/forum/%s" % forum_id)
@http.route('/forum/notification_read', type='json', auth="user", methods=['POST'], website=True)
def notification_read(self, **kwargs):
@@ -529,7 +529,7 @@ class WebsiteForum(http.Controller):
'website': kwargs.get('website'),
'email': kwargs.get('email'),
'city': kwargs.get('city'),
- 'country_id': int(kwargs.get('country')),
+ 'country_id': int(kwargs.get('country')) if kwargs.get('country') else False,
'website_description': kwargs.get('description'),
}, context=request.context)
return werkzeug.utils.redirect("/forum/%s/user/%d" % (slug(forum), user.id))
diff --git a/addons/website_forum/models/forum.py b/addons/website_forum/models/forum.py
index 891ce3b982d..2b28eb465cc 100644
--- a/addons/website_forum/models/forum.py
+++ b/addons/website_forum/models/forum.py
@@ -400,8 +400,9 @@ class Post(osv.Model):
raise KarmaError('Not enough karma to downvote.')
Vote = self.pool['forum.post.vote']
- vote_ids = Vote.search(cr, uid, [('post_id', 'in', ids), ('user_id', '=', uid)], limit=1, context=context)
- new_vote = 0
+ vote_ids = Vote.search(cr, uid, [('post_id', 'in', ids), ('user_id', '=', uid)], context=context)
+ new_vote = '1' if upvote else '-1'
+ voted_forum_ids = set()
if vote_ids:
for vote in Vote.browse(cr, uid, vote_ids, context=context):
if upvote:
@@ -409,9 +410,9 @@ class Post(osv.Model):
else:
new_vote = '0' if vote.vote == '1' else '-1'
Vote.write(cr, uid, vote_ids, {'vote': new_vote}, context=context)
- else:
+ voted_forum_ids.add(vote.post_id.id)
+ for post_id in set(ids) - voted_forum_ids:
for post_id in ids:
- new_vote = '1' if upvote else '-1'
Vote.create(cr, uid, {'post_id': post_id, 'vote': new_vote}, context=context)
return {'vote_count': self._get_vote_count(cr, uid, ids, None, None, context=context)[ids[0]], 'user_vote': new_vote}
diff --git a/addons/website_mail/static/src/js/follow.js b/addons/website_mail/static/src/js/follow.js
index 18c36378328..a8b351efa6c 100644
--- a/addons/website_mail/static/src/js/follow.js
+++ b/addons/website_mail/static/src/js/follow.js
@@ -40,17 +40,21 @@
}
this.$target.removeClass('has-error');
- openerp.jsonRpc('/website_mail/follow', 'call', {
- 'id': +this.$target.data('id'),
- 'object': this.$target.data('object'),
- 'message_is_follower': this.$target.attr("data-follow") || "off",
- 'email': $email.length ? $email.val() : false,
- }).then(function (follow) {
- self.toggle_subscription(follow, self.email);
- });
+ var email = $email.length ? $email.val() : false;
+ if (email) {
+ openerp.jsonRpc('/website_mail/follow', 'call', {
+ 'id': +this.$target.data('id'),
+ 'object': this.$target.data('object'),
+ 'message_is_follower': this.$target.attr("data-follow") || "off",
+ 'email': email,
+ }).then(function (follow) {
+ self.toggle_subscription(follow, email);
+ });
+ }
},
toggle_subscription: function(follow, email) {
console.log(follow, email);
+ follow = follow || (!email && this.$target.attr('data-unsubscribe'));
if (follow) {
this.$target.find(".js_follow_btn").addClass("hidden");
this.$target.find(".js_unfollow_btn").removeClass("hidden");
@@ -60,8 +64,8 @@
this.$target.find(".js_unfollow_btn").addClass("hidden");
}
this.$target.find('input.js_follow_email')
- .val(email ? email : "")
- .attr("disabled", follow || (email.length && this.is_user) ? "disabled" : false);
+ .val(email || "")
+ .attr("disabled", email && (follow || this.is_user) ? "disabled" : false);
this.$target.attr("data-follow", follow ? 'on' : 'off');
},
});
diff --git a/addons/website_mail/views/website_mail.xml b/addons/website_mail/views/website_mail.xml
index 0ccae00e21d..2b810095231 100644
--- a/addons/website_mail/views/website_mail.xml
+++ b/addons/website_mail/views/website_mail.xml
@@ -5,7 +5,8 @@
+ t-att-data-follow="object.id and object.message_is_follower and 'on' or 'off'"
+ t-att-data-unsubscribe="'unsubscribe' if 'unsubscribe' in request.params else None">
' % (base_url, group.id),
+ 'List-Archive': '<%s/groups/%s>' % (base_url, slug(group)),
'List-Subscribe': '<%s/groups>' % (base_url),
- 'List-Unsubscribe': '<%s/groups>' % (base_url),
+ 'List-Unsubscribe': '<%s/groups?unsubscribe>' % (base_url,),
})
res['headers'] = '%s' % headers
return res
+
+
+class MailMail(osv.Model):
+ _inherit = 'mail.mail'
+
+ def send_get_mail_body(self, cr, uid, mail, partner=None, context=None):
+ """ Short-circuit parent method for mail groups, replace the default
+ footer with one appropriate for mailing-lists."""
+
+ if mail.model == 'mail.group' and mail.res_id:
+ # no super() call on purpose, no private links that could be quoted!
+ group = self.pool['mail.group'].browse(cr, uid, mail.res_id, context=context)
+ base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url')
+ vals = {
+ 'maillist': _('Mailing-List'),
+ 'post_to': _('Post to'),
+ 'unsub': _('Unsubscribe'),
+ 'mailto': 'mailto:%s@%s' % (group.alias_name, group.alias_domain),
+ 'group_url': '%s/groups/%s' % (base_url, slug(group)),
+ 'unsub_url': '%s/groups?unsubscribe' % (base_url,),
+ }
+ footer = """_______________________________________________
+ %(maillist)s: %(group_url)s
+ %(post_to)s: %(mailto)s
+ %(unsub)s: %(unsub_url)s
+ """ % vals
+ body = tools.append_content_to_html(mail.body, footer, container_tag='div')
+ return body
+ else:
+ return super(MailMail, self).send_get_mail_body(cr, uid, mail,
+ partner=partner,
+ context=context)
diff --git a/addons/website_mail_group/views/website_mail_group.xml b/addons/website_mail_group/views/website_mail_group.xml
index a1065027748..a5170e28a7b 100644
--- a/addons/website_mail_group/views/website_mail_group.xml
+++ b/addons/website_mail_group/views/website_mail_group.xml
@@ -31,6 +31,9 @@
+
+
Need to unsubscribe? It's right here!
+
diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py
index 5c8bf288f16..e62d8edc82d 100644
--- a/addons/website_sale/controllers/main.py
+++ b/addons/website_sale/controllers/main.py
@@ -660,7 +660,7 @@ class website_sale(http.Controller):
if not order:
return {
'state': 'error',
- 'message': '
There seems to be an error with your request.
',
+ 'message': '
%s
' % _('There seems to be an error with your request.'),
}
tx_ids = request.registry['payment.transaction'].search(
@@ -672,7 +672,7 @@ class website_sale(http.Controller):
if order.amount_total:
return {
'state': 'error',
- 'message': '
There seems to be an error with your request.
',
+ 'message': '
%s
' % _('There seems to be an error with your request.'),
}
else:
state = 'done'
@@ -682,15 +682,15 @@ class website_sale(http.Controller):
tx = request.registry['payment.transaction'].browse(cr, uid, tx_ids[0], context=context)
state = tx.state
if state == 'done':
- message = '
Your payment has been received.
'
+ message = '
%s
' % _('Your payment has been received.')
elif state == 'cancel':
- message = '
The payment seems to have been canceled.
'
+ message = '
%s
' % _('The payment seems to have been canceled.')
elif state == 'pending' and tx.acquirer_id.validation == 'manual':
- message = '
Your transaction is waiting confirmation.
'
+ message = '
%s
' % _('Your transaction is waiting confirmation.')
if tx.acquirer_id.post_msg:
message += tx.acquirer_id.post_msg
else:
- message = '
+ t-att-checked="order.carrier_id and order.carrier_id.id == delivery.id and 'checked' or False"
+ t-att-disabled="delivery.available and '0' or '1'"/>
-
+
+
+
diff --git a/openerp/addons/base/ir/ir_mail_server.py b/openerp/addons/base/ir/ir_mail_server.py
index aeded8a1295..cb5bda830a8 100644
--- a/openerp/addons/base/ir/ir_mail_server.py
+++ b/openerp/addons/base/ir/ir_mail_server.py
@@ -415,6 +415,13 @@ class ir_mail_server(osv.osv):
smtp_to_list = filter(None, tools.flatten(map(extract_rfc2822_addresses,[email_to, email_cc, email_bcc])))
assert smtp_to_list, "At least one valid recipient address should be specified for outgoing emails (To/Cc/Bcc)"
+ x_forge_to = message['X-Forge-To']
+ if x_forge_to:
+ # `To:` header forged, e.g. for posting on mail.groups, to avoid confusion
+ del message['X-Forge-To']
+ del message['To'] # avoid multiple To: headers!
+ message['To'] = x_forge_to
+
# Do not actually send emails in testing mode!
if getattr(threading.currentThread(), 'testing', False):
_test_logger.info("skip sending email in test mode")
diff --git a/openerp/addons/base/ir/ir_values.py b/openerp/addons/base/ir/ir_values.py
index 4720f601f49..f34f02a8aec 100644
--- a/openerp/addons/base/ir/ir_values.py
+++ b/openerp/addons/base/ir/ir_values.py
@@ -319,10 +319,10 @@ class ir_values(osv.osv):
(SELECT company_id from res_users where id = %%s)
)
%s
- ORDER BY v.user_id, u.company_id"""
+ ORDER BY v.user_id, u.company_id, v.key2"""
params = ('default', model, uid, uid)
if condition:
- query %= 'AND v.key2 = %s'
+ query %= 'AND (v.key2 = %s OR v.key2 IS NULL)'
params += (condition[:200],)
else:
query %= 'AND v.key2 is NULL'