diff --git a/addons/delivery/models/delivery_carrier.py b/addons/delivery/models/delivery_carrier.py
index bbe63917..e511dedc 100644
--- a/addons/delivery/models/delivery_carrier.py
+++ b/addons/delivery/models/delivery_carrier.py
@@ -33,7 +33,7 @@ class DeliveryCarrier(models.Model):
# Internals for shipping providers #
# -------------------------------- #
- name = fields.Char(required=True)
+ name = fields.Char(required=True, translate=True)
active = fields.Boolean(default=True)
sequence = fields.Integer(help="Determine the display order", default=10)
# This field will be overwritten by internal shipping providers by adding their own type (ex: 'fedex')
diff --git a/addons/delivery/models/sale_order.py b/addons/delivery/models/sale_order.py
index 8311da99..441ffe1f 100644
--- a/addons/delivery/models/sale_order.py
+++ b/addons/delivery/models/sale_order.py
@@ -91,7 +91,7 @@ class SaleOrder(models.Model):
# Create the sales order line
values = {
'order_id': self.id,
- 'name': carrier.name,
+ 'name': carrier.with_context(lang=self.partner_id.lang).name,
'product_uom_qty': 1,
'product_uom': carrier.product_id.uom_id.id,
'product_id': carrier.product_id.id,
@@ -117,3 +117,7 @@ class SaleOrderLine(models.Model):
if not line.product_id or not line.product_uom or not line.product_uom_qty:
return 0.0
line.product_qty = line.product_uom._compute_quantity(line.product_uom_qty, line.product_id.uom_id)
+
+ def _is_delivery(self):
+ self.ensure_one()
+ return self.is_delivery
diff --git a/addons/delivery/models/stock_picking.py b/addons/delivery/models/stock_picking.py
index 9fa0657c..6b36f334 100644
--- a/addons/delivery/models/stock_picking.py
+++ b/addons/delivery/models/stock_picking.py
@@ -161,8 +161,11 @@ class StockPicking(models.Model):
def send_to_shipper(self):
self.ensure_one()
res = self.carrier_id.send_shipping(self)[0]
+ if self.carrier_id.free_over and self.sale_id and self.sale_id._compute_amount_total_without_delivery() >= self.carrier_id.amount:
+ res['exact_price'] = 0.0
self.carrier_price = res['exact_price']
- self.carrier_tracking_ref = res['tracking_number']
+ if res['tracking_number']:
+ self.carrier_tracking_ref = res['tracking_number']
order_currency = self.sale_id.currency_id or self.company_id.currency_id
msg = _("Shipment sent to carrier %s for shipping with tracking number %s
Cost: %.2f %s") % (self.carrier_id.name, self.carrier_tracking_ref, self.carrier_price, order_currency.name)
self.message_post(body=msg)
diff --git a/addons/delivery/tests/test_delivery_cost.py b/addons/delivery/tests/test_delivery_cost.py
index f782376e..b359a25c 100644
--- a/addons/delivery/tests/test_delivery_cost.py
+++ b/addons/delivery/tests/test_delivery_cost.py
@@ -31,7 +31,10 @@ class TestDeliveryCost(common.TransactionCase):
self.free_delivery = self.env.ref('delivery.free_delivery_carrier')
# as the tests hereunder assume all the prices in USD, we must ensure
# that the company actually uses USD
- self.env.user.company_id.write({'currency_id': self.env.ref('base.USD').id})
+ self.env.cr.execute(
+ "UPDATE res_company SET currency_id = %s WHERE id = %s",
+ [self.env.ref('base.USD').id, self.env.user.company_id.id])
+ self.pricelist.currency_id = self.env.ref('base.USD').id
def test_00_delivery_cost(self):
# In order to test Carrier Cost
diff --git a/addons/event/models/event.py b/addons/event/models/event.py
index 043fe888..a5b2f737 100644
--- a/addons/event/models/event.py
+++ b/addons/event/models/event.py
@@ -438,9 +438,14 @@ class EventRegistration(models.Model):
@api.multi
def message_get_suggested_recipients(self):
recipients = super(EventRegistration, self).message_get_suggested_recipients()
+ public_users = self.env['res.users'].sudo()
+ public_groups = self.env.ref("base.group_public", raise_if_not_found=False)
+ if public_groups:
+ public_users = public_groups.sudo().with_context(active_test=False).mapped("users")
try:
for attendee in self:
- if attendee.partner_id:
+ is_public = attendee.sudo().with_context(active_test=False).partner_id.user_ids in public_users if public_users else False
+ if attendee.partner_id and not is_public:
attendee._message_add_suggested_recipient(recipients, partner=attendee.partner_id, reason=_('Customer'))
elif attendee.email:
attendee._message_add_suggested_recipient(recipients, email=attendee.email, reason=_('Customer Email'))
diff --git a/addons/event/models/event_mail.py b/addons/event/models/event_mail.py
index d6dc257c..8379a264 100644
--- a/addons/event/models/event_mail.py
+++ b/addons/event/models/event_mail.py
@@ -4,7 +4,12 @@ from datetime import datetime
from dateutil.relativedelta import relativedelta
from flectra import api, fields, models, tools
+from flectra.tools import exception_to_unicode
+from flectra.tools.translate import _
+import random
+import logging
+_logger = logging.getLogger(__name__)
_INTERVALS = {
'hours': lambda interval: relativedelta(hours=interval),
@@ -114,13 +119,52 @@ class EventMailScheduler(models.Model):
self.write({'mail_sent': True})
return True
+ @api.model
+ def _warn_template_error(self, scheduler, exception):
+ # We warn ~ once by hour ~ instead of every 10 min if the interval unit is more than 'hours'.
+ if random.random() < 0.1666 or scheduler.interval_unit in ('now', 'hours'):
+ ex_s = exception_to_unicode(exception)
+ try:
+ event, template = scheduler.event_id, scheduler.template_id
+ emails = list(set([event.organizer_id.email, event.user_id.email, template.write_uid.email]))
+ subject = _("WARNING: Event Scheduler Error for event: %s" % event.name)
+ body = _("""Event Scheduler for:
+ - Event: %s (%s)
+ - Scheduled: %s
+ - Template: %s (%s)
+
+ Failed with error:
+ - %s
+
+ You receive this email because you are:
+ - the organizer of the event,
+ - or the responsible of the event,
+ - or the last writer of the template."""
+ % (event.name, event.id, scheduler.scheduled_date, template.name, template.id, ex_s))
+ email = self.env['ir.mail_server'].build_email(
+ email_from=self.env.user.email,
+ email_to=emails,
+ subject=subject, body=body,
+ )
+ self.env['ir.mail_server'].send_email(email)
+ except Exception as e:
+ _logger.error("Exception while sending traceback by email: %s.\n Original Traceback:\n%s", e, exception)
+ pass
+
@api.model
def run(self, autocommit=False):
schedulers = self.search([('done', '=', False), ('scheduled_date', '<=', datetime.strftime(fields.datetime.now(), tools.DEFAULT_SERVER_DATETIME_FORMAT))])
for scheduler in schedulers:
- scheduler.execute()
- if autocommit:
- self.env.cr.commit()
+ try:
+ with self.env.cr.savepoint():
+ scheduler.execute()
+ except Exception as e:
+ _logger.exception(e)
+ self.invalidate_cache()
+ self._warn_template_error(scheduler, e)
+ else:
+ if autocommit:
+ self.env.cr.commit()
return True
diff --git a/addons/event/models/res_partner.py b/addons/event/models/res_partner.py
index ba52eefb..5d13e69c 100644
--- a/addons/event/models/res_partner.py
+++ b/addons/event/models/res_partner.py
@@ -9,6 +9,8 @@ class ResPartner(models.Model):
event_count = fields.Integer("Events", compute='_compute_event_count', help="Number of events the partner has participated.")
def _compute_event_count(self):
+ if not self.user_has_groups('event.group_event_user'):
+ return
for partner in self:
partner.event_count = self.env['event.event'].search_count([('registration_ids.partner_id', 'child_of', partner.ids)])
diff --git a/addons/event/report/event_event_templates.xml b/addons/event/report/event_event_templates.xml
index f083b2b6..3094f9db 100644
--- a/addons/event/report/event_event_templates.xml
+++ b/addons/event/report/event_event_templates.xml
@@ -18,7 +18,7 @@