diff --git a/addons/delivery/models/stock_picking.py b/addons/delivery/models/stock_picking.py
index 75b14aa7a7b..ad2bf8a8e15 100644
--- a/addons/delivery/models/stock_picking.py
+++ b/addons/delivery/models/stock_picking.py
@@ -152,6 +152,7 @@ class StockPicking(models.Model):
'context': dict(
self.env.context,
current_package_carrier_type=self.carrier_id.delivery_type,
+ default_picking_id=self.id, # DO NOT FORWARD PORT
default_stock_quant_package_id=res.id
),
}
diff --git a/addons/delivery/wizard/choose_delivery_package.py b/addons/delivery/wizard/choose_delivery_package.py
index e7ad1d75292..422e3a1893e 100644
--- a/addons/delivery/wizard/choose_delivery_package.py
+++ b/addons/delivery/wizard/choose_delivery_package.py
@@ -37,14 +37,15 @@ class ChooseDeliveryPackage(models.TransientModel):
return res
def _default_shipping_weight(self):
- if self.env.context.get('default_stock_quant_package_id'):
- stock_quant_package = self.env['stock.quant.package'].browse(self.env.context['default_stock_quant_package_id'])
- return stock_quant_package.shipping_weight
- else:
- picking_id = self.env['stock.picking'].browse(self.env.context['active_id'])
- move_line_ids = [po for po in picking_id.move_line_ids if po.qty_done > 0 and not po.result_package_id]
+ package_id = self.env.context.get('default_stock_quant_package_id')
+ picking_id = self.env.context.get('default_picking_id')
+ if package_id and picking_id: # DO NOT FORWARD PORT
+ picking = self.env['stock.picking'].browse(picking_id)
+ move_line_ids = [po for po in picking.move_line_ids if po.qty_done > 0 and po.result_package_id.id == package_id]
total_weight = sum([po.qty_done * po.product_id.weight for po in move_line_ids])
return total_weight
+ else:
+ return 0
@api.depends('stock_quant_package_id', 'delivery_packaging_id')
def _compute_weight_uom_name(self):
diff --git a/addons/google_calendar/models/google_calendar.py b/addons/google_calendar/models/google_calendar.py
index 9155cf9a0fa..bf9010f3023 100644
--- a/addons/google_calendar/models/google_calendar.py
+++ b/addons/google_calendar/models/google_calendar.py
@@ -81,7 +81,7 @@ class SyncEvent(object):
self.OP = Delete((self.OE.status and "OE") or (self.GG.status and "GG"),
'The event has been deleted from one side, we delete on other side !')
#If event is not deleted !
- elif self.OE.status and (self.GG.status or not is_owner):
+ elif self.OE.status and (self.GG.status or (not is_owner and self.GG.update)):
if abs(self.OE.update - self.GG.update) > timedelta(seconds=1):
if self.OE.update < self.GG.update:
tmpSrc = 'GG'
diff --git a/addons/google_spreadsheet/models/google_drive.py b/addons/google_spreadsheet/models/google_drive.py
index 32402ffe626..f3c04608e72 100644
--- a/addons/google_spreadsheet/models/google_drive.py
+++ b/addons/google_spreadsheet/models/google_drive.py
@@ -35,7 +35,7 @@ class GoogleDrive(models.Model):
if not modifiers.get('invisible') and not modifiers.get('column_invisible'):
display_fields.append(node.get('name'))
fields = " ".join(display_fields)
- domain = domain.replace("'", r"\'").replace('"', "'")
+ domain = domain.replace("'", r"\'").replace('"', "'").replace('True', 'true').replace('False', 'false')
if groupbys:
fields = "%s %s" % (groupbys, fields)
formula = '=oe_read_group("%s";"%s";"%s";"%s")' % (model, fields, groupbys, domain)
diff --git a/addons/mail/models/mail_mail.py b/addons/mail/models/mail_mail.py
index a2ba820656f..5875ab42ee2 100644
--- a/addons/mail/models/mail_mail.py
+++ b/addons/mail/models/mail_mail.py
@@ -172,6 +172,8 @@ class MailMail(models.Model):
messages._notify_failure_update() # notify user that we have a failure
(notifications - failed).sudo().write({
'email_status': 'sent',
+ 'failure_type': '',
+ 'failure_reason': '',
})
if not failure_type or failure_type == 'RECIPIENT': # if we have another error, we want to keep the mail.
mail_to_delete_ids = [mail.id for mail in self if mail.auto_delete]
diff --git a/addons/mail/static/src/js/composers/basic_composer.js b/addons/mail/static/src/js/composers/basic_composer.js
index 9def912612c..1beeea18644 100644
--- a/addons/mail/static/src/js/composers/basic_composer.js
+++ b/addons/mail/static/src/js/composers/basic_composer.js
@@ -536,6 +536,7 @@ var BasicComposer = Widget.extend({
files: ev.currentTarget.files,
submitForm: true
});
+ ev.target.value = "";
},
/**
* @private
diff --git a/addons/mrp/models/mrp_workorder.py b/addons/mrp/models/mrp_workorder.py
index 861faf383be..59e2599f2ff 100644
--- a/addons/mrp/models/mrp_workorder.py
+++ b/addons/mrp/models/mrp_workorder.py
@@ -249,7 +249,7 @@ class MrpWorkorder(models.Model):
self.qty_producing = float_round(self.production_id.product_qty - self.qty_produced, precision_rounding=rounding)
self.generate_wo_lines()
- if self.next_work_order_id and self.production_id.product_id.tracking != 'none':
+ if self.next_work_order_id and self.next_work_order_id.state not in ['done', 'cancel'] and self.production_id.product_id.tracking != 'none':
self.next_work_order_id._assign_default_final_lot_id()
if float_compare(self.qty_produced, self.production_id.product_qty, precision_rounding=rounding) >= 0:
diff --git a/addons/payment/views/payment_templates.xml b/addons/payment/views/payment_templates.xml
index 550939e21b7..64afb0b016f 100644
--- a/addons/payment/views/payment_templates.xml
+++ b/addons/payment/views/payment_templates.xml
@@ -87,6 +87,9 @@
Save my payment data
+
+
+
diff --git a/addons/project/views/project_portal_templates.xml b/addons/project/views/project_portal_templates.xml
index 14498944913..1bb202f8fd8 100644
--- a/addons/project/views/project_portal_templates.xml
+++ b/addons/project/views/project_portal_templates.xml
@@ -238,7 +238,7 @@
diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py
index ec6729064ae..745419c98a0 100644
--- a/addons/sale/models/sale.py
+++ b/addons/sale/models/sale.py
@@ -1242,6 +1242,7 @@ class SaleOrderLine(models.Model):
:param additional_domain: domain to restrict AAL to include in computation (required since timesheet is an AAL with a project ...)
"""
result = {}
+
# avoid recomputation if no SO lines concerned
if not self:
return result
diff --git a/addons/snailmail/models/ir_actions_report.py b/addons/snailmail/models/ir_actions_report.py
index 2a1ad2f9496..b441d55c0fb 100644
--- a/addons/snailmail/models/ir_actions_report.py
+++ b/addons/snailmail/models/ir_actions_report.py
@@ -6,6 +6,14 @@ from odoo import models, fields, api, _
class IrActionsReport(models.Model):
_inherit = 'ir.actions.report'
+ @api.multi
+ def retrieve_attachment(self, record):
+ # Override this method in order to force to re-render the pdf in case of
+ # using snailmail
+ if self.env.context.get('snailmail_layout'):
+ return False
+ return super(IrActionsReport, self).retrieve_attachment(record)
+
@api.model
def get_paperformat(self):
# force the right format (euro/A4) when sending letters, only if we are not using the l10n_DE layout
diff --git a/addons/stock/data/stock_data.xml b/addons/stock/data/stock_data.xml
index d522f76d9c6..b38a917f891 100644
--- a/addons/stock/data/stock_data.xml
+++ b/addons/stock/data/stock_data.xml
@@ -14,6 +14,8 @@
+
+
Physical Locationsview
diff --git a/addons/stock/models/stock_quant.py b/addons/stock/models/stock_quant.py
index 66a7aa90b8c..f43374dad61 100644
--- a/addons/stock/models/stock_quant.py
+++ b/addons/stock/models/stock_quant.py
@@ -433,5 +433,5 @@ class QuantPackage(models.Model):
for quant in self._get_contained_quants():
if quant.product_id not in res:
res[quant.product_id] = 0
- res[quant.product_id] += quant.qty
+ res[quant.product_id] += quant.quantity
return res
diff --git a/addons/uom/models/uom_uom.py b/addons/uom/models/uom_uom.py
index f98b0dc67bb..04368b3624c 100644
--- a/addons/uom/models/uom_uom.py
+++ b/addons/uom/models/uom_uom.py
@@ -83,9 +83,8 @@ class UoM(models.Model):
self._cr.execute("""
SELECT C.id AS category_id, count(U.id) AS uom_count
FROM uom_category C
- LEFT JOIN uom_uom U ON C.id = U.category_id AND uom_type = 'reference'
+ LEFT JOIN uom_uom U ON C.id = U.category_id AND uom_type = 'reference' AND U.active = 't'
WHERE C.id IN %s
- AND U.active = 't'
GROUP BY C.id
""", (tuple(category_ids),))
for uom_data in self._cr.dictfetchall():
diff --git a/addons/uom/tests/test_uom.py b/addons/uom/tests/test_uom.py
index 66207639f77..c6fe98dd81e 100644
--- a/addons/uom/tests/test_uom.py
+++ b/addons/uom/tests/test_uom.py
@@ -68,6 +68,16 @@ class TestUom(TransactionCase):
'name': 'Custom UoM category',
})
+ # at first we can not create a non reference in custom category
+ with self.assertRaises(ValidationError):
+ self.env['uom.uom'].create({
+ 'name': 'Bigger UoM of my category',
+ 'factor_inv': 42,
+ 'uom_type': 'bigger',
+ 'rounding': 0.5,
+ 'category_id': category.id
+ })
+
# create the reference
self.env['uom.uom'].create({
'name': 'Reference UoM of my category',
diff --git a/addons/web/static/src/scss/layout_boxed.scss b/addons/web/static/src/scss/layout_boxed.scss
index 2129f583b21..bc4f5a6c2fb 100644
--- a/addons/web/static/src/scss/layout_boxed.scss
+++ b/addons/web/static/src/scss/layout_boxed.scss
@@ -1,5 +1,5 @@
.o_boxed_footer, .o_boxed_header, .o_report_layout_boxed {
- font-family: 'Lato' 'Noto';
+ font-family: 'Lato', 'Noto';
color: gray('700');
font-size: 12px;
}
diff --git a/addons/website/models/website.py b/addons/website/models/website.py
index 0c63ee55f41..82e4f36107f 100644
--- a/addons/website/models/website.py
+++ b/addons/website/models/website.py
@@ -141,7 +141,7 @@ class Website(models.Model):
public_user_to_change_websites = self.env['website']
self._get_languages.clear_cache(self)
if 'company_id' in values and 'user_id' not in values:
- public_user_to_change_websites = self.filtered(lambda w: w.user_id.company_id.id != values['company_id'])
+ public_user_to_change_websites = self.filtered(lambda w: w.sudo().user_id.company_id.id != values['company_id'])
if public_user_to_change_websites:
company = self.env['res.company'].browse(values['company_id'])
super(Website, public_user_to_change_websites).write(dict(values, user_id=company._get_public_user().id))
diff --git a/addons/website_sale/static/src/js/website_sale_options.js b/addons/website_sale/static/src/js/website_sale_options.js
index 619ea92f6b5..f98aad44a5f 100644
--- a/addons/website_sale/static/src/js/website_sale_options.js
+++ b/addons/website_sale/static/src/js/website_sale_options.js
@@ -129,11 +129,20 @@ sAnimations.registry.WebsiteSaleOptions = sAnimations.Class.extend(ProductConfig
* @param {integer} quantity
*/
_onOptionsUpdateQuantity: function (quantity) {
- this.$form
+ var $qtyInput = this.$form
.find('.js_main_product input[name="add_qty"]')
- .first()
- .val(quantity)
- .trigger('change');
+ .first();
+
+ if ($qtyInput.length) {
+ $qtyInput.val(quantity).trigger('change');
+ } else {
+ // This handles the case when the "Select Quantity" customize show
+ // is disabled, and therefore the above selector does not find an
+ // element.
+ // To avoid duplicating all RPC, only trigger the variant change if
+ // it is not already done from the above trigger.
+ this.optionalProductsModal.triggerVariantChange(this.optionalProductsModal.$el);
+ }
},
/**
diff --git a/addons/website_sale_wishlist/models/product_wishlist.py b/addons/website_sale_wishlist/models/product_wishlist.py
index 7467991f3a7..1bcbe57baef 100644
--- a/addons/website_sale_wishlist/models/product_wishlist.py
+++ b/addons/website_sale_wishlist/models/product_wishlist.py
@@ -7,7 +7,7 @@ from odoo.http import request
class ProductWishlist(models.Model):
_name = 'product.wishlist'
_description = 'Product Wishlist'
- _sql_constrains = [
+ _sql_constraints = [
("product_unique_partner_id",
"UNIQUE(product_id, partner_id)",
"Duplicated wishlisted product for this partner."),
diff --git a/odoo/addons/test_new_api/__manifest__.py b/odoo/addons/test_new_api/__manifest__.py
index e238f37f779..ec4bdae82bc 100644
--- a/odoo/addons/test_new_api/__manifest__.py
+++ b/odoo/addons/test_new_api/__manifest__.py
@@ -10,7 +10,9 @@
'data': [
'ir.model.access.csv',
'views.xml',
- 'demo_data.xml',
'template.xml',
],
+ 'demo': [
+ 'demo_data.xml',
+ ],
}
diff --git a/odoo/http.py b/odoo/http.py
index 886fecc48ba..217720f6a72 100644
--- a/odoo/http.py
+++ b/odoo/http.py
@@ -280,13 +280,15 @@ class WebRequest(object):
_request_stack.pop()
if self._cr:
- if exc_type is None and not self._failed:
- self._cr.commit()
- if self.registry:
- self.registry.signal_changes()
- elif self.registry:
- self.registry.reset_changes()
- self._cr.close()
+ try:
+ if exc_type is None and not self._failed:
+ self._cr.commit()
+ if self.registry:
+ self.registry.signal_changes()
+ elif self.registry:
+ self.registry.reset_changes()
+ finally:
+ self._cr.close()
# just to be sure no one tries to re-use the request
self.disable_db = True
self.uid = None