summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2017-12-04 20:12:19 +0100
committerChristophe Simonis <chs@odoo.com>2017-12-04 20:12:19 +0100
commita8d01cbf4ea88f894ff927a6a5424bbb58e630d0 (patch)
treeb5f52af75dec36eac2bf44941f3c5f7d8ab3a1ed /addons
parent3549688b21eb65e16b9c3f2b6462eb8d8b52cd47 (diff)
parenta447da75fd6f3c76aa4db80d9a83d5e56fa0854d (diff)
[MERGE] forward port branch saas-15 up to a447da75fd6
Diffstat (limited to 'addons')
-rw-r--r--addons/account/models/chart_template.py2
-rw-r--r--addons/mrp/wizard/change_production_qty.py2
-rw-r--r--addons/point_of_sale/static/src/js/screens.js9
-rw-r--r--addons/product/models/product.py7
-rw-r--r--addons/product/views/product_views.xml2
-rw-r--r--addons/project/models/project.py5
-rw-r--r--addons/web/static/src/js/chrome/search_inputs.js2
-rw-r--r--addons/web/static/src/js/fields/basic_fields.js7
-rw-r--r--addons/web/static/src/js/views/graph/graph_renderer.js2
-rw-r--r--addons/web_editor/static/src/js/rte.js4
-rw-r--r--addons/website/static/src/js/website.snippets.animation.js35
-rw-r--r--addons/website_sale/controllers/main.py2
-rw-r--r--addons/website_sale/views/templates.xml7
13 files changed, 61 insertions, 25 deletions
diff --git a/addons/account/models/chart_template.py b/addons/account/models/chart_template.py
index da20b325a3b..2f734dde9ba 100644
--- a/addons/account/models/chart_template.py
+++ b/addons/account/models/chart_template.py
@@ -756,7 +756,7 @@ class WizardMultiChartsAccounts(models.TransientModel):
if company_id:
company = self.env['res.company'].browse(company_id)
currency_id = company.on_change_country(company.country_id.id)['value']['currency_id']
- res.update({'currency_id': currency_id})
+ res.update({'currency_id': currency_id.id})
chart_templates = account_chart_template.search([('visible', '=', True)])
if chart_templates:
diff --git a/addons/mrp/wizard/change_production_qty.py b/addons/mrp/wizard/change_production_qty.py
index e9588516a0c..3422edd8cb5 100644
--- a/addons/mrp/wizard/change_production_qty.py
+++ b/addons/mrp/wizard/change_production_qty.py
@@ -68,7 +68,7 @@ class ChangeProductionQty(models.TransientModel):
cycle_number * operation.time_cycle * 100.0 / operation.workcenter_id.time_efficiency)
quantity = wo.qty_production - wo.qty_produced
if production.product_id.tracking == 'serial':
- quantity = 1.0 if float_is_zero(quantity, precision_digits=precision) else 0.0
+ quantity = 1.0 if not float_is_zero(quantity, precision_digits=precision) else 0.0
else:
quantity = quantity if (quantity > 0) else 0
if float_is_zero(quantity, precision_digits=precision):
diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js
index 8cf2f5d9a7d..65e4de7faa1 100644
--- a/addons/point_of_sale/static/src/js/screens.js
+++ b/addons/point_of_sale/static/src/js/screens.js
@@ -1125,12 +1125,15 @@ var ClientListScreenWidget = ScreenWidget.extend({
var self = this;
var order = this.pos.get_order();
if( this.has_client_changed() ){
- if ( this.new_client ) {
+ var default_fiscal_position_id = _.find(this.pos.fiscal_positions, function(fp) {
+ return fp.id === self.pos.config.default_fiscal_position_id[0];
+ });
+ if ( this.new_client && this.new_client.property_account_position_id ) {
order.fiscal_position = _.find(this.pos.fiscal_positions, function (fp) {
return fp.id === self.new_client.property_account_position_id[0];
- });
+ }) || default_fiscal_position_id;
} else {
- order.fiscal_position = undefined;
+ order.fiscal_position = default_fiscal_position_id;
}
order.set_client(this.new_client);
diff --git a/addons/product/models/product.py b/addons/product/models/product.py
index fc21bb7c4bd..d7e9f71705d 100644
--- a/addons/product/models/product.py
+++ b/addons/product/models/product.py
@@ -46,10 +46,13 @@ class ProductCategory(models.Model):
category.complete_name = category.name
def _compute_product_count(self):
- read_group_res = self.env['product.template'].read_group([('categ_id', 'in', self.ids)], ['categ_id'], ['categ_id'])
+ read_group_res = self.env['product.template'].read_group([('categ_id', 'child_of', self.ids)], ['categ_id'], ['categ_id'])
group_data = dict((data['categ_id'][0], data['categ_id_count']) for data in read_group_res)
for categ in self:
- categ.product_count = group_data.get(categ.id, 0)
+ product_count = 0
+ for sub_categ_id in categ.search([('id', 'child_of', categ.id)]).ids:
+ product_count += group_data.get(sub_categ_id, 0)
+ categ.product_count = product_count
@api.constrains('parent_id')
def _check_category_recursion(self):
diff --git a/addons/product/views/product_views.xml b/addons/product/views/product_views.xml
index 31eeba88bde..6393f99d003 100644
--- a/addons/product/views/product_views.xml
+++ b/addons/product/views/product_views.xml
@@ -112,7 +112,7 @@
<field name="arch" type="xml">
<search string="Product">
<field name="name" string="Product" filter_domain="['|','|',('default_code','ilike',self),('name','ilike',self),('barcode','ilike',self)]"/>
- <field name="categ_id" filter_domain="[('categ_id', 'child_of', self)]"/>
+ <field name="categ_id" filter_domain="[('categ_id', 'child_of', raw_value)]"/>
<separator/>
<filter string="Services" name="services" domain="[('type','=','service')]"/>
<filter string="Products" name="consumable" domain="[('type', 'in', ['consu', 'product'])]"/>
diff --git a/addons/project/models/project.py b/addons/project/models/project.py
index 2e108e94e3d..bfeb11ccd7f 100644
--- a/addons/project/models/project.py
+++ b/addons/project/models/project.py
@@ -245,7 +245,8 @@ class Project(models.Model):
project = super(Project, self).copy(default)
for follower in self.message_follower_ids:
project.message_subscribe(partner_ids=follower.partner_id.ids, subtype_ids=follower.subtype_ids.ids)
- self.map_tasks(project.id)
+ if 'tasks' not in default:
+ self.map_tasks(project.id)
return project
@api.model
@@ -269,6 +270,8 @@ class Project(models.Model):
if 'active' in vals:
# archiving/unarchiving a project does it on its tasks, too
self.with_context(active_test=False).mapped('tasks').write({'active': vals['active']})
+ # archiving/unarchiving a project implies that we don't want to use the analytic account anymore
+ self.with_context(active_test=False).mapped('analytic_account_id').write({'active': vals['active']})
if vals.get('partner_id') or vals.get('privacy_visibility'):
for project in self.filtered(lambda project: project.privacy_visibility == 'portal'):
project.message_subscribe(project.partner_id.ids)
diff --git a/addons/web/static/src/js/chrome/search_inputs.js b/addons/web/static/src/js/chrome/search_inputs.js
index d567551873f..a2923d1a607 100644
--- a/addons/web/static/src/js/chrome/search_inputs.js
+++ b/addons/web/static/src/js/chrome/search_inputs.js
@@ -153,7 +153,7 @@ var Field = Input.extend( /** @lends instance.web.search.Field# */ {
value_to_domain = function (facetValue) {
return Domain.prototype.stringToArray(
domain,
- {self: self.value_from(facetValue)}
+ {self: self.value_from(facetValue), raw_value: facetValue.attributes.value}
);
};
} else {
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js
index ce1a305277f..069e004c702 100644
--- a/addons/web/static/src/js/fields/basic_fields.js
+++ b/addons/web/static/src/js/fields/basic_fields.js
@@ -1176,7 +1176,7 @@ var FieldBinaryFile = AbstractFieldBinary.extend({
template: 'FieldBinaryFile',
events: _.extend({}, AbstractFieldBinary.prototype.events, {
'click': function (event) {
- if (this.mode === 'readonly' && this.value) {
+ if (this.mode === 'readonly' && this.value && this.recordData.id) {
this.on_save_as(event);
}
},
@@ -1193,6 +1193,11 @@ var FieldBinaryFile = AbstractFieldBinary.extend({
this.do_toggle(!!this.value);
if (this.value) {
this.$el.empty().append($("<span/>").addClass('fa fa-download'));
+ if (this.recordData.id) {
+ this.$el.css('cursor', 'pointer');
+ } else {
+ this.$el.css('cursor', 'not-allowed');
+ }
if (this.filename_value) {
this.$el.append(" " + this.filename_value);
}
diff --git a/addons/web/static/src/js/views/graph/graph_renderer.js b/addons/web/static/src/js/views/graph/graph_renderer.js
index 6a976c3a588..4e6c3692aad 100644
--- a/addons/web/static/src/js/views/graph/graph_renderer.js
+++ b/addons/web/static/src/js/views/graph/graph_renderer.js
@@ -81,7 +81,7 @@ return AbstractRenderer.extend({
setTimeout(function () {
self.$el.empty();
var chart = self['_render' + _.str.capitalize(self.state.mode) + 'Chart']();
- if (chart) {
+ if (chart && chart.tooltip.chartContainer) {
self.to_remove = chart.update;
nv.utils.onWindowResize(chart.update);
chart.tooltip.chartContainer(self.el);
diff --git a/addons/web_editor/static/src/js/rte.js b/addons/web_editor/static/src/js/rte.js
index f2fb2753642..3f813367ca3 100644
--- a/addons/web_editor/static/src/js/rte.js
+++ b/addons/web_editor/static/src/js/rte.js
@@ -355,8 +355,8 @@ var RTE = Widget.extend({
var $el = $(this);
$el.find('[class]').filter(function () {
- if (!this.className.match(/\S/)) {
- this.removeAttribute("class");
+ if (!this.getAttribute('class').match(/\S/)) {
+ this.removeAttribute('class');
}
});
diff --git a/addons/website/static/src/js/website.snippets.animation.js b/addons/website/static/src/js/website.snippets.animation.js
index 1213b986472..bed19b0acde 100644
--- a/addons/website/static/src/js/website.snippets.animation.js
+++ b/addons/website/static/src/js/website.snippets.animation.js
@@ -415,16 +415,35 @@ animation.registry.media_video = animation.Class.extend({
start: function () {
// TODO: this code should be refactored to make more sense and be better
// integrated with Odoo (this refactoring should be done in master).
- this.$target.find('iframe').remove();
- if (!this.$target.has('.media_iframe_video_size').length) {
- var editor = '<div class="css_editable_mode_display">&nbsp;</div>';
- var size = '<div class="media_iframe_video_size">&nbsp;</div>';
- this.$target.html(editor+size);
+ var def = this._super.apply(this, arguments);
+ if (this.$target.children('iframe').length) {
+ // There already is an <iframe/>, do nothing
+ return def;
}
- // rebuilding the iframe, from https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
- this.$target.html(this.$target.html()+'<iframe sandbox="allow-scripts allow-same-origin" src="'+_.escape(this.$target.data("oe-expression"))+'" frameborder="0" allowfullscreen="allowfullscreen"></iframe>');
- return this._super.apply(this, arguments);
+
+ // Bug fix / compatibility: empty the <div/> element as all information
+ // to rebuild the iframe should have been saved on the <div/> element
+ this.$target.empty();
+
+ // Add extra content for size / edition
+ this.$target.append(
+ '<div class="css_editable_mode_display">&nbsp;</div>' +
+ '<div class="media_iframe_video_size">&nbsp;</div>'
+ );
+
+ // Rebuild the iframe. Depending on version / compatibility / instance,
+ // the src is saved in the 'data-src' attribute or the
+ // 'data-oe-expression' one (the latter is used as a workaround in 10.0
+ // system but should obviously be reviewed in master).
+ this.$target.append($('<iframe/>', {
+ src: _.escape(this.$target.data('oe-expression') || this.$target.data('src')),
+ frameborder: '0',
+ allowfullscreen: 'allowfullscreen',
+ sandbox: 'allow-scripts allow-same-origin', // https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
+ }));
+
+ return def;
},
});
diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py
index d3235391fe2..19c3f3b5b02 100644
--- a/addons/website_sale/controllers/main.py
+++ b/addons/website_sale/controllers/main.py
@@ -429,7 +429,7 @@ class WebsiteSale(http.Controller):
Partner = order.partner_id.with_context(show_address=1).sudo()
shippings = Partner.search([
("id", "child_of", order.partner_id.commercial_partner_id.ids),
- '|', ("type", "=", "delivery"), ("id", "=", order.partner_id.commercial_partner_id.id)
+ '|', ("type", "in", ["delivery", "other"]), ("id", "=", order.partner_id.commercial_partner_id.id)
], order='id desc')
if shippings:
if kw.get('partner_id') or 'use_billing' in kw:
diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml
index 339645a46aa..332c1bb238c 100644
--- a/addons/website_sale/views/templates.xml
+++ b/addons/website_sale/views/templates.xml
@@ -1106,6 +1106,7 @@
<t t-foreach="shippings" t-as="ship">
<div class="col-sm-12 col-md-6 one_kanban">
<t t-call="website_sale.address_kanban">
+ <t t-set="actual_partner" t-value="order.partner_id" />
<t t-set='contact' t-value="ship"/>
<t t-set='selected' t-value="order.partner_shipping_id==ship"/>
<t t-set='readonly' t-value="bool(len(shippings)==1)"/>
@@ -1139,7 +1140,7 @@
</t>
<input type='submit'/>
</form>
- <a class='btn btn-link pull-right fa fa-edit js_edit_address no-decoration' title="Edit this address"></a>
+ <a t-if="not actual_partner or (ship.id in actual_partner.ids + actual_partner.child_ids.ids)" class='btn btn-link pull-right fa fa-edit js_edit_address no-decoration' title="Edit this address"></a>
<div t-att-class="'panel panel-default %s' % (selected and 'border_primary' or 'js_change_shipping')">
<div class='panel-body' style='min-height: 130px;'>
<t t-esc="contact" t-options="dict(widget='contact', fields=['name', 'address'], no_marker=True)"/>
@@ -1175,7 +1176,9 @@
<t t-if="mode == ('new', 'billing')">
<h3 class="page-header mt32 ml16">Your Address
<small> or </small>
- <t t-set='connect' t-value="request.env['ir.config_parameter'].sudo().get_param('auth_signup.allow_uninvited') == 'True' and ('signup', 'Sign Up') or ('login', 'Log In')"/>
+ <t t-set="signup_text">Sign Up</t>
+ <t t-set="login_text">Log In</t>
+ <t t-set='connect' t-value="request.env['ir.config_parameter'].sudo().get_param('auth_signup.allow_uninvited') == 'True' and ('signup', signup_text) or ('login', login_text)"/>
<a t-attf-href='/web/{{connect[0]}}?redirect=/shop/checkout' class='btn btn-primary' style="margin-top: -11px"><t t-esc='connect[1]'/></a>
</h3>
</t>