@@ -774,7 +774,7 @@
tree,kanban,form,calendar,pivot,graph
[('type','=','in_refund')]
- {'default_type': 'in_refund', 'journal_type': 'purchase'}
+ {'default_type': 'in_refund', 'type': 'in_refund', 'journal_type': 'purchase'}
diff --git a/addons/account/views/report_journal.xml b/addons/account/views/report_journal.xml
index ebeff1f3d7f..06dbab99ae4 100644
--- a/addons/account/views/report_journal.xml
+++ b/addons/account/views/report_journal.xml
@@ -49,7 +49,7 @@
|
|
|
- |
+ |
|
|
|
diff --git a/addons/auth_ldap/models/res_company_ldap.py b/addons/auth_ldap/models/res_company_ldap.py
index 4f280530bbe..92914a93c4d 100644
--- a/addons/auth_ldap/models/res_company_ldap.py
+++ b/addons/auth_ldap/models/res_company_ldap.py
@@ -6,6 +6,7 @@ import logging
from ldap.filter import filter_format
from odoo import api, fields, models, tools
+from odoo.tools.pycompat import to_native
_logger = logging.getLogger(__name__)
@@ -107,7 +108,7 @@ class CompanyLDAP(models.Model):
if len(results) == 1:
dn = results[0][0]
conn = self.connect(conf)
- conn.simple_bind_s(dn, password.encode('utf-8'))
+ conn.simple_bind_s(dn, to_native(password))
conn.unbind()
entry = results[0]
except ldap.INVALID_CREDENTIALS:
@@ -144,8 +145,8 @@ class CompanyLDAP(models.Model):
conn = self.connect(conf)
ldap_password = conf['ldap_password'] or ''
ldap_binddn = conf['ldap_binddn'] or ''
- conn.simple_bind_s(ldap_binddn.encode('utf-8'), ldap_password.encode('utf-8'))
- results = conn.search_st(conf['ldap_base'].encode('utf-8'), ldap.SCOPE_SUBTREE, filter, retrieve_attributes, timeout=60)
+ conn.simple_bind_s(to_native(ldap_binddn), to_native(ldap_password))
+ results = conn.search_st(to_native(conf['ldap_base']), ldap.SCOPE_SUBTREE, filter, retrieve_attributes, timeout=60)
conn.unbind()
except ldap.INVALID_CREDENTIALS:
_logger.error('LDAP bind failed.')
diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py
index 7669357c342..6d5b1649dc3 100644
--- a/addons/point_of_sale/models/pos_order.py
+++ b/addons/point_of_sale/models/pos_order.py
@@ -917,7 +917,7 @@ class PosOrderLine(models.Model):
self.tax_ids = self.product_id.taxes_id.filtered(lambda r: not self.company_id or r.company_id == self.company_id)
fpos = self.order_id.fiscal_position_id
tax_ids_after_fiscal_position = fpos.map_tax(self.tax_ids, self.product_id, self.order_id.partner_id) if fpos else self.tax_ids
- self.price_unit = self.env['account.tax']._fix_tax_included_price(price, self.product_id.taxes_id, tax_ids_after_fiscal_position)
+ self.price_unit = self.env['account.tax']._fix_tax_included_price_company(price, self.product_id.taxes_id, tax_ids_after_fiscal_position, self.company_id)
@api.onchange('qty', 'discount', 'price_unit', 'tax_ids')
def _onchange_qty(self):
diff --git a/addons/purchase/models/purchase.py b/addons/purchase/models/purchase.py
index 422c0bd30f6..efeab4979dc 100644
--- a/addons/purchase/models/purchase.py
+++ b/addons/purchase/models/purchase.py
@@ -825,7 +825,7 @@ class PurchaseOrderLine(models.Model):
if not seller:
return
- price_unit = self.env['account.tax']._fix_tax_included_price(seller.price, self.product_id.supplier_taxes_id, self.taxes_id) if seller else 0.0
+ price_unit = self.env['account.tax']._fix_tax_included_price_company(seller.price, self.product_id.supplier_taxes_id, self.taxes_id, self.company_id) if seller else 0.0
if price_unit and seller and self.order_id.currency_id and seller.currency_id != self.order_id.currency_id:
price_unit = seller.currency_id.compute(price_unit, self.order_id.currency_id)
@@ -908,7 +908,7 @@ class ProcurementRule(models.Model):
date=po.date_order and po.date_order[:10],
uom_id=product_id.uom_po_id)
- price_unit = self.env['account.tax']._fix_tax_included_price(seller.price, line.product_id.supplier_taxes_id, line.taxes_id) if seller else 0.0
+ price_unit = self.env['account.tax']._fix_tax_included_price_company(seller.price, line.product_id.supplier_taxes_id, line.taxes_id, values['company_id']) if seller else 0.0
if price_unit and seller and po.currency_id and seller.currency_id != po.currency_id:
price_unit = seller.currency_id.compute(price_unit, po.currency_id)
@@ -955,7 +955,7 @@ class ProcurementRule(models.Model):
if taxes_id:
taxes_id = taxes_id.filtered(lambda x: x.company_id.id == values['company_id'].id)
- price_unit = self.env['account.tax']._fix_tax_included_price(seller.price, product_id.supplier_taxes_id, taxes_id) if seller else 0.0
+ price_unit = self.env['account.tax']._fix_tax_included_price_company(seller.price, product_id.supplier_taxes_id, taxes_id, values['company_id']) if seller else 0.0
if price_unit and seller and po.currency_id and seller.currency_id != po.currency_id:
price_unit = seller.currency_id.compute(price_unit, po.currency_id)
diff --git a/addons/report_intrastat/views/report_intrastat_views.xml b/addons/report_intrastat/views/report_intrastat_views.xml
index 86247cb0fd9..4c6766248ce 100644
--- a/addons/report_intrastat/views/report_intrastat_views.xml
+++ b/addons/report_intrastat/views/report_intrastat_views.xml
@@ -93,7 +93,7 @@
report.intrastat.kanban
report.intrastat
-
+
diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py
index a9f053dbe7e..b3a5035c6bc 100644
--- a/addons/sale/models/sale.py
+++ b/addons/sale/models/sale.py
@@ -1021,7 +1021,7 @@ class SaleOrderLine(models.Model):
self._compute_tax_id()
if self.order_id.pricelist_id and self.order_id.partner_id:
- vals['price_unit'] = self.env['account.tax']._fix_tax_included_price(self._get_display_price(product), product.taxes_id, self.tax_id)
+ vals['price_unit'] = self.env['account.tax']._fix_tax_included_price_company(self._get_display_price(product), product.taxes_id, self.tax_id, self.company_id)
self.update(vals)
return result
@@ -1041,7 +1041,7 @@ class SaleOrderLine(models.Model):
uom=self.product_uom.id,
fiscal_position=self.env.context.get('fiscal_position')
)
- self.price_unit = self.env['account.tax']._fix_tax_included_price(self._get_display_price(product), product.taxes_id, self.tax_id)
+ self.price_unit = self.env['account.tax']._fix_tax_included_price_company(self._get_display_price(product), product.taxes_id, self.tax_id, self.company_id)
@api.multi
def unlink(self):
@@ -1117,7 +1117,7 @@ class SaleOrderLine(models.Model):
price, rule_id = self.order_id.pricelist_id.with_context(pricelist_context).get_product_price_rule(self.product_id, self.product_uom_qty or 1.0, self.order_id.partner_id)
new_list_price, currency_id = self.with_context(context_partner)._get_real_price_currency(self.product_id, rule_id, self.product_uom_qty, self.product_uom, self.order_id.pricelist_id.id)
- new_list_price = self.env['account.tax']._fix_tax_included_price(new_list_price, self.product_id.taxes_id, self.tax_id)
+ new_list_price = self.env['account.tax']._fix_tax_included_price_company(new_list_price, self.product_id.taxes_id, self.tax_id, self.company_id)
if new_list_price != 0:
if self.product_id.company_id and self.order_id.pricelist_id.currency_id != self.product_id.company_id.currency_id:
diff --git a/addons/sale/views/sale_views.xml b/addons/sale/views/sale_views.xml
index ef7ec08ab35..c06c2bf165d 100644
--- a/addons/sale/views/sale_views.xml
+++ b/addons/sale/views/sale_views.xml
@@ -248,6 +248,7 @@
diff --git a/addons/sale_payment/models/payment.py b/addons/sale_payment/models/payment.py
index 75dfbcadb11..fab6f546d6f 100644
--- a/addons/sale_payment/models/payment.py
+++ b/addons/sale_payment/models/payment.py
@@ -87,7 +87,7 @@ class PaymentTransaction(models.Model):
_logger.warning('<%s> transaction completed, could not auto-generate payment for %s (ID %s) (no journal set on acquirer)',
self.acquirer_id.provider, self.sale_order_id.name, self.sale_order_id.id)
self.acquirer_id.journal_id = default_journal
- created_invoice.pay_and_reconcile(self.acquirer_id.journal_id, pay_amount=created_invoice.amount_total)
+ created_invoice.with_context(tx_currency_id=self.currency_id.id).pay_and_reconcile(self.acquirer_id.journal_id, pay_amount=created_invoice.amount_total)
if created_invoice.payment_ids:
created_invoice.payment_ids[0].payment_transaction_id = self
else:
diff --git a/addons/stock/models/procurement.py b/addons/stock/models/procurement.py
index 988a87ada71..105416390de 100644
--- a/addons/stock/models/procurement.py
+++ b/addons/stock/models/procurement.py
@@ -302,6 +302,13 @@ class ProcurementGroup(models.Model):
1000 orderpoints.
This is appropriate for batch jobs only.
"""
+ if company_id and self.env.user.company_id.id != company_id:
+ # To ensure that the company_id is taken into account for
+ # all the processes triggered by this method
+ # i.e. If a PO is generated by the run of the procurements the
+ # sequence to use is the one for the specified company not the
+ # one of the user's company
+ self = self.with_context(company_id=company_id, force_company=company_id)
OrderPoint = self.env['stock.warehouse.orderpoint']
domain = self._get_orderpoint_domain(company_id=company_id)
orderpoints_noprefetch = OrderPoint.with_context(prefetch_fields=False).search(domain,
diff --git a/addons/web/static/src/js/chrome/view_manager.js b/addons/web/static/src/js/chrome/view_manager.js
index c19fd8ab3e2..10b7838b58e 100644
--- a/addons/web/static/src/js/chrome/view_manager.js
+++ b/addons/web/static/src/js/chrome/view_manager.js
@@ -294,12 +294,7 @@ var ViewManager = Widget.extend(ControlPanelMixin, {
}).fail(view.loaded.reject.bind(view.loaded));
} else {
view.loaded = view.loaded.then(function() {
- // By default, the view will be loaded in readonly mode
- // Returns to this default mode if you load action from breadcrumb
view_options = _.extend({}, view_options, self.env);
- if (view_type === 'form') {
- view_options.mode = view_options.mode || 'readonly';
- }
return view.controller.reload(view_options);
});
}
@@ -384,8 +379,14 @@ var ViewManager = Widget.extend(ControlPanelMixin, {
});
},
select_view: function (index) {
- var view_type = this.view_stack[index].type;
- return this.switch_mode(view_type);
+ var viewType = this.view_stack[index].type;
+ var viewOptions = {};
+ if (viewType === 'form') {
+ // reload form views in readonly, except for inline actions (i.e.
+ // settings views) that stay in edit
+ viewOptions.mode = this.action.target === 'inline' ? 'edit' : 'readonly';
+ }
+ return this.switch_mode(viewType, viewOptions);
},
/**
* Renders the switch buttons for multi- and mono-record views and adds
diff --git a/addons/web/static/src/js/views/basic/basic_controller.js b/addons/web/static/src/js/views/basic/basic_controller.js
index 46359188577..481fc0cf4dd 100644
--- a/addons/web/static/src/js/views/basic/basic_controller.js
+++ b/addons/web/static/src/js/views/basic/basic_controller.js
@@ -71,7 +71,7 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
return $.when(false);
}
- var message = _t("The record has been modified, your changes will be discarded. Are you sure you want to ?");
+ var message = _t("The record has been modified, your changes will be discarded. Do you want to proceed?");
var def = $.Deferred();
var dialog = Dialog.confirm(this, message, {
title: _t("Warning"),
diff --git a/addons/web/static/src/js/views/form/form_renderer.js b/addons/web/static/src/js/views/form/form_renderer.js
index 9c71c9eb2a3..db47f93588d 100644
--- a/addons/web/static/src/js/views/form/form_renderer.js
+++ b/addons/web/static/src/js/views/form/form_renderer.js
@@ -13,6 +13,7 @@ var FormRenderer = BasicRenderer.extend({
className: "o_form_view",
events: _.extend({}, BasicRenderer.prototype.events, {
'click .o_notification_box .oe_field_translate': '_onTranslate',
+ 'click .oe_title, .o_group': '_onClick',
}),
/**
* @override
@@ -832,6 +833,16 @@ var FormRenderer = BasicRenderer.extend({
// Handlers
//--------------------------------------------------------------------------
+ /**
+ * Makes the Edit button bounce in readonly
+ *
+ * @private
+ */
+ _onClick: function () {
+ if (this.mode === 'readonly') {
+ this.trigger_up('bounce_edit');
+ }
+ },
/**
* @override
* @private
diff --git a/addons/web/static/src/js/views/list/list_editable_renderer.js b/addons/web/static/src/js/views/list/list_editable_renderer.js
index 89aa3d865dd..06058069ab6 100644
--- a/addons/web/static/src/js/views/list/list_editable_renderer.js
+++ b/addons/web/static/src/js/views/list/list_editable_renderer.js
@@ -192,6 +192,7 @@ ListRenderer.include({
* @param {string} recordID
*/
removeLine: function (state, recordID) {
+ var self = this;
var rowIndex = _.findIndex(this.state.data, {id: recordID});
this.state = state;
if (rowIndex === -1) {
@@ -746,6 +747,17 @@ ListRenderer.include({
this._super.apply(this, arguments);
}
},
+ /**
+ * Overrides to prevent from sorting if we are currently editing a record.
+ *
+ * @override
+ * @private
+ */
+ _onSortColumn: function () {
+ if (this.currentRow === null) {
+ this._super.apply(this, arguments);
+ }
+ },
/**
* Triggers a delete event. I don't know why we stop the propagation of the
* event.
diff --git a/addons/web/static/src/js/widgets/date_picker.js b/addons/web/static/src/js/widgets/date_picker.js
index 26b73c27ac5..3573e9232e5 100644
--- a/addons/web/static/src/js/widgets/date_picker.js
+++ b/addons/web/static/src/js/widgets/date_picker.js
@@ -75,9 +75,16 @@ var DateWidget = Widget.extend({
* set datetime value
*/
changeDatetime: function () {
- if(this.isValid()) {
+ if (this.isValid()) {
+ var oldValue = this.getValue();
this._setValueFromUi();
- this.trigger("datetime_changed");
+ var newValue = this.getValue();
+
+ if (!oldValue !== !newValue || oldValue && newValue && !oldValue.isSame(newValue)) {
+ // The condition is strangely written; this is because the
+ // values can be false/undefined
+ this.trigger("datetime_changed");
+ }
}
},
/**
diff --git a/addons/web/static/src/less/rainbow.less b/addons/web/static/src/less/rainbow.less
index ba63437fc2f..ec5a701d31d 100644
--- a/addons/web/static/src/less/rainbow.less
+++ b/addons/web/static/src/less/rainbow.less
@@ -2,6 +2,7 @@
// Variables
@reward-size: 400px;
+@reward-size-mobile: 300px;
@reward-text-color: #727880;
@reward-base-time: 1.4s;
@@ -11,6 +12,9 @@
z-index: @zindex-modal + 1;
padding: 50px;
margin: -5% auto 0 -(@reward-size / 2);
+ @media (max-width: @screen-xs-max) {
+ margin: -5% auto 0 -(@reward-size-mobile / 2);
+ }
background-image: -webkit-radial-gradient(#EDEFF4 30%, transparent 70%, transparent);
background-image: -o-radial-gradient(#EDEFF4 30%, transparent 70%, transparent);
background-image: radial-gradient(#EDEFF4 30%, transparent 70%, transparent);
@@ -18,6 +22,9 @@
.o-animation(reward-fading, @reward-base-time * 0.5, ease-in-out, 0s, 1, normal, forwards);
.o-position-absolute(20%, auto, auto, 50%);
.size(@reward-size, @reward-size);
+ @media (max-width: @screen-xs-max) {
+ .size(@reward-size-mobile, @reward-size-mobile);
+ }
&.o_reward_fading {
display: block;
@@ -70,6 +77,9 @@
.o_reward_stars {
display: block;
.size(@reward-size * 0.75, @reward-size / 2);
+ @media (max-width: @screen-xs-max) {
+ .size(@reward-size-mobile * 0.75, @reward-size-mobile / 2);
+ }
.o-position-absolute(18%, 7%);
svg {
diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js
index 716e581b44a..6a3fdb0fbea 100644
--- a/addons/web/static/tests/views/form_tests.js
+++ b/addons/web/static/tests/views/form_tests.js
@@ -5946,5 +5946,36 @@ QUnit.module('Views', {
delete widgetRegistry.map.test;
});
+ QUnit.test('bounce edit button in readonly mode', function (assert) {
+ assert.expect(3);
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '',
+ res_id: 1,
+ intercepts: {
+ bounce_edit: function() {
+ assert.step('bounce');
+ },
+ },
+ });
+
+ // in readonly
+ form.$('[name="display_name"]').click();
+ assert.verifySteps(['bounce']);
+
+ // in edit
+ form.$buttons.find('.o_form_button_edit').click();
+ form.$('[name="display_name"]').click();
+ assert.verifySteps(['bounce']);
+
+ form.destroy();
+ });
});
});
diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js
index 0f1725b6d82..52149f008eb 100644
--- a/addons/web/static/tests/views/list_tests.js
+++ b/addons/web/static/tests/views/list_tests.js
@@ -487,6 +487,39 @@ QUnit.module('Views', {
list.destroy();
});
+ QUnit.test('editable list view: save data when list sorting in edit mode', function (assert) {
+ assert.expect(3);
+
+ this.data.foo.fields.foo.sortable = true;
+
+ var list = createView({
+ View: ListView,
+ model: 'foo',
+ data: this.data,
+ arch: '',
+ mockRPC: function (route, args) {
+ if (args.method === 'write') {
+ assert.deepEqual(args.args, [[1], {foo: 'xyz'}],
+ "should correctly save the edited record");
+ }
+ return this._super.apply(this, arguments);
+ }
+ });
+
+ list.$('.o_data_cell:first').click();
+ list.$('input[name="foo"]').val('xyz').trigger('input');
+ list.$('.o_column_sortable').click();
+
+ assert.ok(list.$('.o_data_row:first').hasClass('o_selected_row'),
+ "first row should still be in edition");
+
+ list.$buttons.find('.o_list_button_save').click();
+ assert.ok(!list.$buttons.hasClass('o-editing'),
+ "list buttons should be back to their readonly mode");
+
+ list.destroy();
+ });
+
QUnit.test('selection changes are triggered correctly', function (assert) {
assert.expect(8);
@@ -912,6 +945,7 @@ QUnit.module('Views', {
assert.ok(form.$('tbody tr:eq(2) td input').val(),
"Value 2 should be third (shouldn't be sorted)");
+ form.$('.o_form_sheet_bg').click(); // validate the row before sorting
$o2m.find('.o_column_sortable').click();
assert.ok(form.$('tbody tr:first td:contains(Value 3)').length,
"Value 3 should be first");
diff --git a/addons/web/static/tests/widgets/domain_selector_tests.js b/addons/web/static/tests/widgets/domain_selector_tests.js
index 19731156a2c..77d8eeb24da 100644
--- a/addons/web/static/tests/widgets/domain_selector_tests.js
+++ b/addons/web/static/tests/widgets/domain_selector_tests.js
@@ -151,7 +151,7 @@ QUnit.module('DomainSelector', {
});
QUnit.test("building a domain with a datetime", function (assert) {
- assert.expect(1);
+ assert.expect(2);
var $target = $("#qunit-fixture");
@@ -163,8 +163,16 @@ QUnit.module('DomainSelector', {
domainSelector.appendTo($target);
// Check that there is a datepicker to choose the date
- assert.strictEqual(domainSelector.$(".o_datepicker:visible").length, 1,
+ var $datepicker = domainSelector.$(".o_datepicker:visible");
+ assert.strictEqual($datepicker.length, 1,
"there should be a datepicker");
+
+ var val = $datepicker.find('input').focus().click().val();
+ $('.bootstrap-datetimepicker-widget :not(.today)[data-action="selectDay"]').click();
+ assert.notEqual(domainSelector.$(".o_datepicker:visible input").val(), val,
+ "datepicker value should have changed");
+
+ domainSelector.destroy();
});
});
});
diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py
index ce230e56e1b..5298a1ce7a0 100644
--- a/addons/website_sale/models/sale_order.py
+++ b/addons/website_sale/models/sale_order.py
@@ -97,7 +97,7 @@ class SaleOrder(models.Model):
if order.pricelist_id and order.partner_id:
order_line = order._cart_find_product_line(product.id)
if order_line:
- pu = self.env['account.tax']._fix_tax_included_price(pu, product.taxes_id, order_line[0].tax_id)
+ pu = self.env['account.tax']._fix_tax_included_price_company(pu, product.taxes_id, order_line[0].tax_id, self.company_id)
return {
'product_id': product_id,
@@ -185,10 +185,11 @@ class SaleOrder(models.Model):
'pricelist': order.pricelist_id.id,
})
product = self.env['product.product'].with_context(product_context).browse(product_id)
- values['price_unit'] = self.env['account.tax']._fix_tax_included_price(
+ values['price_unit'] = self.env['account.tax']._fix_tax_included_price_company(
order_line._get_display_price(product),
order_line.product_id.taxes_id,
- order_line.tax_id
+ order_line.tax_id,
+ self.company_id
)
order_line.write(values)
diff --git a/doc/reference/testing.rst b/doc/reference/testing.rst
index 7b5bb666988..ab32a9d3e0a 100644
--- a/doc/reference/testing.rst
+++ b/doc/reference/testing.rst
@@ -48,6 +48,11 @@ related to testing Odoo content (modules, mainly):
.. autoclass:: odoo.tests.common.SingleTransactionCase
:members: browse_ref, ref
+.. autoclass:: odoo.tests.common.SavepointCase
+
+.. autoclass:: odoo.tests.common.HttpCase
+ :members: browse_ref, ref, url_open, phantom_js
+
By default, tests are run once right after the corresponding module has been
installed. Test cases can also be configured to run after all modules have
been installed, and not run right after the module installation:
diff --git a/odoo/addons/base/ir/ir_http.py b/odoo/addons/base/ir/ir_http.py
index f4d830efe12..255f034d994 100644
--- a/odoo/addons/base/ir/ir_http.py
+++ b/odoo/addons/base/ir/ir_http.py
@@ -228,7 +228,7 @@ class IrHttp(models.AbstractModel):
if not hasattr(cls, '_routing_map'):
_logger.info("Generating routing map")
installed = request.registry._init_modules - {'web'}
- if tools.config['test_enable']:
+ if tools.config['test_enable'] and odoo.modules.module.current_test:
installed.add(odoo.modules.module.current_test)
mods = [''] + odoo.conf.server_wide_modules + sorted(installed)
# Note : when routing map is generated, we put it on the class `cls`
diff --git a/odoo/addons/base/res/res_partner_view.xml b/odoo/addons/base/res/res_partner_view.xml
index 31b689826d0..e1933a5184c 100644
--- a/odoo/addons/base/res/res_partner_view.xml
+++ b/odoo/addons/base/res/res_partner_view.xml
@@ -283,6 +283,11 @@
+
+
+
+
+
diff --git a/odoo/addons/base/static/pdf/preview_background.pdf b/odoo/addons/base/static/pdf/preview_background.pdf
index e69de29bb2d..d33687c16b8 100644
Binary files a/odoo/addons/base/static/pdf/preview_background.pdf and b/odoo/addons/base/static/pdf/preview_background.pdf differ
diff --git a/odoo/addons/base/static/pdf/preview_boxed.pdf b/odoo/addons/base/static/pdf/preview_boxed.pdf
index e69de29bb2d..e73c1131d04 100644
Binary files a/odoo/addons/base/static/pdf/preview_boxed.pdf and b/odoo/addons/base/static/pdf/preview_boxed.pdf differ
diff --git a/odoo/addons/base/static/pdf/preview_clean.pdf b/odoo/addons/base/static/pdf/preview_clean.pdf
index e69de29bb2d..4f1c42b4814 100644
Binary files a/odoo/addons/base/static/pdf/preview_clean.pdf and b/odoo/addons/base/static/pdf/preview_clean.pdf differ
diff --git a/odoo/addons/base/static/pdf/preview_standard.pdf b/odoo/addons/base/static/pdf/preview_standard.pdf
index e69de29bb2d..4d537376850 100644
Binary files a/odoo/addons/base/static/pdf/preview_standard.pdf and b/odoo/addons/base/static/pdf/preview_standard.pdf differ
diff --git a/odoo/cli/shell.py b/odoo/cli/shell.py
index 0aaa9ab2d84..e75e453a231 100644
--- a/odoo/cli/shell.py
+++ b/odoo/cli/shell.py
@@ -63,7 +63,7 @@ class Shell(Command):
def console(self, local_vars):
if not os.isatty(sys.stdin.fileno()):
- exec(sys.stdin, local_vars)
+ exec(sys.stdin.read(), local_vars)
else:
if 'env' not in local_vars:
print('No environment set, use `%s shell -d dbname` to get one.' % sys.argv[0])