diff options
| author | Christophe Simonis <chs@odoo.com> | 2017-12-06 11:59:38 +0100 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2017-12-06 11:59:38 +0100 |
| commit | f96a797fe6238306ec70d3db013b8a4d348ef181 (patch) | |
| tree | 40990f6ca69840a52421c4a52f68e439ba1a5b42 /addons | |
| parent | dc5755698cc41e0c5f51ab5dccee1356a0f23a3f (diff) | |
| parent | b8540eefe3b82fc4a54c8a808ce3bfa0bea8a29a (diff) | |
[MERGE] forward port branch saas-16 up to b8540eefe3b
Diffstat (limited to 'addons')
26 files changed, 150 insertions, 50 deletions
diff --git a/addons/account/models/chart_template.py b/addons/account/models/chart_template.py index eaacb3721cc..9121e9f115e 100644 --- a/addons/account/models/chart_template.py +++ b/addons/account/models/chart_template.py @@ -769,7 +769,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/account/static/src/js/reconciliation/reconciliation_model.js b/addons/account/static/src/js/reconciliation/reconciliation_model.js index 8f81b700168..b77882323a3 100644 --- a/addons/account/static/src/js/reconciliation/reconciliation_model.js +++ b/addons/account/static/src/js/reconciliation/reconciliation_model.js @@ -605,9 +605,14 @@ var StatementModel = BasicModel.extend({ var line = self.getLine(handle); var props = _.filter(line.reconciliation_proposition, function (prop) {return !prop.is_tax && !prop.invalid;}); if (props.length === 0) { + // Usability: if user has not choosen any lines and click validate, it has the same behavior + // as creating a write-off of the same amount. props.push(self._formatQuickCreate(line, { account_id: [line.st_line.open_balance_account_id, self.accounts[line.st_line.open_balance_account_id]], })); + // update balance of line otherwise it won't be to zero and another line will be added + line.reconciliation_proposition.push(props[0]); + self._computeLine(line); } ids.push(line.id); var values_dict = { diff --git a/addons/auth_oauth/data/auth_oauth_data.xml b/addons/auth_oauth/data/auth_oauth_data.xml index 1b1ff532ae4..8417c9c4b2d 100644 --- a/addons/auth_oauth/data/auth_oauth_data.xml +++ b/addons/auth_oauth/data/auth_oauth_data.xml @@ -16,7 +16,7 @@ <field name="auth_endpoint">https://www.facebook.com/dialog/oauth</field> <field name="scope">public_profile,email</field> <field name="validation_endpoint">https://graph.facebook.com/me</field> - <field name="data_endpoint"></field> + <field name="data_endpoint">https://graph.facebook.com/me?fields=id,name,email</field> <field name="css_class">fa fa-facebook-square</field> <field name="body">Log in with facebook</field> </record> diff --git a/addons/hr_payroll/data/hr_payroll_data.xml b/addons/hr_payroll/data/hr_payroll_data.xml index c4b16bd05a4..2eede6d92bb 100644 --- a/addons/hr_payroll/data/hr_payroll_data.xml +++ b/addons/hr_payroll/data/hr_payroll_data.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <odoo> - <data noupdate="1"> + <data noupdate="0"> <record id="contrib_register_employees" model="hr.contribution.register"> <field name="name">Employees</field> <field name="partner_id" eval="False"/> diff --git a/addons/l10n_be_hr_payroll/data/l10n_be_hr_payroll_data.xml b/addons/l10n_be_hr_payroll/data/l10n_be_hr_payroll_data.xml index 537021de787..28ed0b1dc14 100644 --- a/addons/l10n_be_hr_payroll/data/l10n_be_hr_payroll_data.xml +++ b/addons/l10n_be_hr_payroll/data/l10n_be_hr_payroll_data.xml @@ -91,7 +91,7 @@ <field name="code">SALARY</field> <field name="condition_select">none</field> <field name="amount_select">code</field> - <field name="amount_python_compute">result = contract.wage * 1.08</field> + <field name="amount_python_compute">result = categories.BASIC * 1.08</field> </record> <record id="hr_payroll_rules_employee" model="hr.salary.rule"> <field name="category_id" ref="hr_payroll_head_salary"/> @@ -100,7 +100,7 @@ <field name="condition_select">none</field> <field name="amount_select">code</field> <field name="amount_python_compute"> -result = contract.wage +result = categories.BASIC if contract.internet: result += 5.0 if contract.mobile: @@ -163,14 +163,15 @@ elif salary <= 2461.27: <field name="condition_python">result = (((employee.marital=='single') or (employee.marital=='married' and employee.spouse_fiscal_status=='without income')) and (employee.resident_bool!=True))</field> <field name="amount_select">code</field> <field name="amount_python_compute"> -if contract.wage >= 0.01 and contract.wage <= 1095.09: +wage = categories.BASIC +if wage >= 0.01 and wage <= 1095.09: result = 0.0 -elif contract.wage >= 1095.10 and contract.wage <= 1945.38: +elif wage >= 1095.10 and wage <= 1945.38: result = 0.0 -elif contract.wage >= 1945.39 and contract.wage <= 2190.18: - result = -min((contract.wage - 1945.38) * 0.076, 18.60) -elif contract.wage >= 2190.19 and contract.wage <= 6038.82: - result = -min(18.60 + (contract.wage - 2190.18) * 0.011, 60.94) +elif wage >= 1945.39 and wage <= 2190.18: + result = -min((wage - 1945.38) * 0.076, 18.60) +elif wage >= 2190.19 and wage <= 6038.82: + result = -min(18.60 + (wage - 2190.18) * 0.011, 60.94) else: result = -60.94 </field> @@ -186,14 +187,15 @@ else: <field name="condition_python">result = (((employee.marital=='married' and employee.spouse_fiscal_status=='with income')) and (employee.resident_bool!=True))</field> <field name="amount_select">code</field> <field name="amount_python_compute"> -if contract.wage >= 0.01 and contract.wage <= 1095.09: +wage = categories.BASIC +if wage >= 0.01 and wage <= 1095.09: result = 0.0 -elif contract.wage >= 1095.10 and contract.wage <= 1945.38: +elif wage >= 1095.10 and wage <= 1945.38: result = -9.30 -elif contract.wage >= 1945.39 and contract.wage <= 2190.18: - result = -min(max((contract.wage - 1945.38) * 0.076, 9.30), 18.60) -elif contract.wage >= 2190.19 and contract.wage <= 6038.82: - result = -min(18.60 + (contract.wage - 2190.18) * 0.011, 51.64) +elif wage >= 1945.39 and wage <= 2190.18: + result = -min(max((wage - 1945.38) * 0.076, 9.30), 18.60) +elif wage >= 2190.19 and wage <= 6038.82: + result = -min(18.60 + (wage - 2190.18) * 0.011, 51.64) else: result = -51.64 </field> @@ -635,7 +637,7 @@ result = -contract.car_atn <field name="code">holidays</field> <field name="default_value">20.0</field> <field name="lower_bound">0.0</field> - <field name="upper_bound">30.0</field> + <field name="upper_bound">35.0</field> </record> <record id="hr_contract_advantage_template_representation_fees" model="hr.contract.advantage.template"> <field name="name">Representation fees</field> diff --git a/addons/l10n_be_hr_payroll/models/l10n_be_hr_payroll.py b/addons/l10n_be_hr_payroll/models/l10n_be_hr_payroll.py index 9174c408f64..e6d11322c6e 100644 --- a/addons/l10n_be_hr_payroll/models/l10n_be_hr_payroll.py +++ b/addons/l10n_be_hr_payroll/models/l10n_be_hr_payroll.py @@ -19,8 +19,8 @@ class HrContract(models.Model): public_transport_employee_amount = fields.Monetary('Paid by the employee (Monthly)') thirteen_month = fields.Monetary(compute='_compute_holidays_advantages', string='13th Month', help="Yearly gross amount the employee receives as 13th month bonus.") - double_holidays = fields.Monetary(compute='_compute_holidays_advantages', string='Double Holidays', - help="Yearly gross amount the employee receives as double holidays bonus.") + double_holidays = fields.Monetary(compute='_compute_holidays_advantages', string='Holiday Bonus', + help="Yearly gross amount the employee receives as holidays bonus.") warrant_value_employee = fields.Monetary(compute='_compute_warrants_cost', string="Warrant value for the employee") # Employer costs fields @@ -67,7 +67,7 @@ class HrContract(models.Model): help="Number of days of paid leaves the employee gets per year.") holidays_editable = fields.Boolean(string="Editable Leaves", default=True) holidays_compensation = fields.Monetary(compute='_compute_holidays_compensation', string="Holidays Compensation") - wage_with_holidays = fields.Monetary(compute='_compute_wage_with_holidays', sting="Wage update with holidays retenues") + wage_with_holidays = fields.Monetary(compute='_compute_wage_with_holidays', string="Wage update with holidays retenues") additional_net_amount = fields.Monetary(string="Net Supplements", help="Monthly net amount the employee receives.") retained_net_amount = fields.Monetary(sting="Net Retained", @@ -116,7 +116,7 @@ class HrContract(models.Model): contract.transport_employer_cost ) - @api.depends('yearly_cost_before_charges', 'social_security_contributions', + @api.depends('yearly_cost_before_charges', 'social_security_contributions', 'wage', 'social_security_contributions', 'double_holidays', 'warrants_cost', 'meal_voucher_paid_by_employer') def _compute_final_yearly_costs(self): for contract in self: diff --git a/addons/l10n_be_hr_payroll/views/l10n_be_hr_payroll_view.xml b/addons/l10n_be_hr_payroll/views/l10n_be_hr_payroll_view.xml index 0d6f6b7fde3..4e7d429f102 100644 --- a/addons/l10n_be_hr_payroll/views/l10n_be_hr_payroll_view.xml +++ b/addons/l10n_be_hr_payroll/views/l10n_be_hr_payroll_view.xml @@ -57,7 +57,7 @@ </div> <field name="monthly_yearly_costs"/> </group> - <group string="Monthly Benefits"> + <group string="Monthly Benefit in Kind"> <field name="transport_mode" widget="radio"/> <field name="car_atn" attrs="{'invisible': [('transport_mode', '!=', 'company_car')]}" invisible="1"/> <field name="transport_employer_cost" invisible="1"/> @@ -109,7 +109,7 @@ <field name="double_holidays" nolabel="1"/> <span>/ year</span> </div> - <field name="holidays_editable"/> + <field name="holidays_editable" invisible="1"/> <label for="holidays"/> <div class="o_row"> <field name="holidays" nolabel="1" attrs="{'readonly': [('holidays_editable', '=', False)]}"/> diff --git a/addons/mrp/wizard/change_production_qty.py b/addons/mrp/wizard/change_production_qty.py index 39f60d319ea..90db7f09481 100644 --- a/addons/mrp/wizard/change_production_qty.py +++ b/addons/mrp/wizard/change_production_qty.py @@ -67,7 +67,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/db.js b/addons/point_of_sale/static/src/js/db.js index e8ec348288b..dc93133be09 100644 --- a/addons/point_of_sale/static/src/js/db.js +++ b/addons/point_of_sale/static/src/js/db.js @@ -301,7 +301,7 @@ var PosDB = core.Class.extend({ search_partner: function(query){ try { query = query.replace(/[\[\]\(\)\+\*\?\.\-\!\&\^\$\|\~\_\{\}\:\,\\\/]/g,'.'); - query = query.replace(' ','.+'); + query = query.replace(/ /g,'.+'); var re = RegExp("([0-9]+):.*?"+query,"gi"); }catch(e){ return []; diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index 8f5e1b9808b..f3a077cf881 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -1166,11 +1166,12 @@ var ClientListScreenWidget = ScreenWidget.extend({ save_changes: function(){ var order = this.pos.get_order(); if( this.has_client_changed() ){ + var default_fiscal_position_id = _.findWhere(this.pos.fiscal_positions, {'id': self.pos.config.default_fiscal_position_id[0]}); if ( this.new_client ) { order.fiscal_position = _.findWhere(this.pos.fiscal_positions, {'id': this.new_client.property_account_position_id[0]}); order.set_pricelist(_.findWhere(this.pos.pricelists, {'id': this.new_client.property_product_pricelist[0]}) || this.pos.default_pricelist); } else { - order.fiscal_position = undefined; + order.fiscal_position = default_fiscal_position_id; order.set_pricelist(this.pos.default_pricelist); } diff --git a/addons/product/models/product.py b/addons/product/models/product.py index d0aed74bc66..62347b4cd06 100644 --- a/addons/product/models/product.py +++ b/addons/product/models/product.py @@ -42,10 +42,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 0e192af09c2..b540deacd01 100644 --- a/addons/product/views/product_views.xml +++ b/addons/product/views/product_views.xml @@ -116,7 +116,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 178ab8b5c66..a873dea6d59 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 @@ -265,6 +266,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/sales_team/models/crm_team.py b/addons/sales_team/models/crm_team.py index 5589d2e0aa0..cf95b66a7e2 100644 --- a/addons/sales_team/models/crm_team.py +++ b/addons/sales_team/models/crm_team.py @@ -24,7 +24,7 @@ class CrmTeam(models.Model): def _get_default_team_id(self, user_id=None): if not user_id: user_id = self.env.uid - company_id = self.sudo(user_id).company_id.id + company_id = self.sudo(user_id).env.user.company_id.id team_id = self.env['crm.team'].sudo().search([ '|', ('user_id', '=', user_id), ('member_ids', '=', user_id), '|', ('company_id', '=', False), ('company_id', 'child_of', [company_id]) diff --git a/addons/web/static/lib/bootstrap-datetimepicker/src/js/bootstrap-datetimepicker.js b/addons/web/static/lib/bootstrap-datetimepicker/src/js/bootstrap-datetimepicker.js index 8f0724bbb00..19f261ff4fc 100644 --- a/addons/web/static/lib/bootstrap-datetimepicker/src/js/bootstrap-datetimepicker.js +++ b/addons/web/static/lib/bootstrap-datetimepicker/src/js/bootstrap-datetimepicker.js @@ -479,8 +479,12 @@ }, notifyEvent = function (e) { - if (e.type === 'dp.change' && ((e.date && e.date.isSame(e.oldDate)) || (!e.date && !e.oldDate))) { - return; + if (e.type === 'dp.change') { + // check _isUTC flag to ensure that we are not comparing apples and oranges + var bothUTC = e.date && e.oldDate && e.date._isUTC === e.oldDate._isUTC; + if ((bothUTC && e.date.isSame(e.oldDate)) || (!e.date && !e.oldDate)) { + return; + } } element.trigger(e); }, diff --git a/addons/web/static/src/js/chrome/search_filters.js b/addons/web/static/src/js/chrome/search_filters.js index e2eff03546d..582af7e70ef 100644 --- a/addons/web/static/src/js/chrome/search_filters.js +++ b/addons/web/static/src/js/chrome/search_filters.js @@ -248,6 +248,10 @@ var Date = DateTime.extend({ attributes: { type: 'date' }, + get_value: function (index) { + // retrieve the datepicker value + return this["datewidget_" + (index || 0)].getValue(); + }, _get_widget_class: function () { return datepicker.DateWidget; }, 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/chrome/search_view.js b/addons/web/static/src/js/chrome/search_view.js index ecd7db41a7d..7b7b3afcd70 100644 --- a/addons/web/static/src/js/chrome/search_view.js +++ b/addons/web/static/src/js/chrome/search_view.js @@ -339,7 +339,7 @@ var SearchView = Widget.extend({ }, set_default_filters: function () { var self = this, - default_custom_filter = this.$buttons && this.favorite_menu.get_default_filter(); + default_custom_filter = this.$buttons && this.favorite_menu && this.favorite_menu.get_default_filter(); if (!self.options.disable_custom_filters && default_custom_filter) { return this.favorite_menu.toggle_filter(default_custom_filter, true); } diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index 7ebe94f7b30..6f4bf1630f8 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -1219,7 +1219,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); } }, @@ -1236,10 +1236,20 @@ 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); } } + if (!this.res_id) { + this.$el.css('cursor', 'not-allowed'); + } else { + this.$el.css('cursor', 'pointer'); + } }, _renderEdit: function () { if (this.value) { @@ -1264,7 +1274,7 @@ var FieldBinaryFile = AbstractFieldBinary.extend({ if (!this.value) { this.do_warn(_t("Save As..."), _t("The field is empty, there's nothing to save !")); ev.stopPropagation(); - } else { + } else if (this.res_id) { framework.blockUI(); var c = crash_manager; var filename_fieldname = this.attrs.filename; 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 2c3a7a7db19..74443843405 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/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 5064dd81af1..4a418c05b72 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -1389,6 +1389,51 @@ QUnit.module('basic_fields', { session.get_file = oldGetFile; }); + QUnit.test('binary fields that are readonly in create mode do not download', function (assert) { + assert.expect(2); + + // save the session function + var oldGetFile = session.get_file; + session.get_file = function (option) { + assert.step('We shouldn\'t be getting the file.'); + return oldGetFile.bind(session)(option); + }; + + this.data.partner.onchanges = { + product_id: function (obj) { + obj.document = "onchange==\n"; + }, + }; + + this.data.partner.fields.document.readonly = true; + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '<form string="Partners">' + + '<field name="product_id"/>' + + '<field name="document" filename="\'yooo\'"/>' + + '</form>', + res_id: 1, + }); + + form.$buttons.find('.o_form_button_create').click(); + var $dropdown = form.$('.o_field_many2one input').autocomplete('widget'); + + form.$('.o_field_many2one input').click(); + $dropdown.find('li:not(.o_m2o_dropdown_option):contains(xphone)').click(); + + assert.strictEqual(form.$('a.o_field_widget[name="document"] > .fa-download').length, 1, + 'The link to download the binary should be present'); + + form.$('a.o_field_widget[name="document"]').click(); + + assert.verifySteps([]); // We shoudln't have passed through steps + + form.destroy(); + session.get_file = oldGetFile; + }); QUnit.test('text field rendering in list view', function (assert) { assert.expect(1); diff --git a/addons/web_editor/static/src/js/backend/fields.js b/addons/web_editor/static/src/js/backend/fields.js index 00c02e20513..95afaa90073 100644 --- a/addons/web_editor/static/src/js/backend/fields.js +++ b/addons/web_editor/static/src/js/backend/fields.js @@ -51,6 +51,9 @@ var FieldTextHtmlSimple = basic_fields.DebouncedField.extend(TranslatableFieldMi var layoutInfo = this.$textarea.data('layoutInfo'); $.summernote.pluginEvents.codeview(undefined, undefined, layoutInfo, false); } + if (this._getValue() !== this.value) { + this._isDirty = true; + } this._super.apply(this, arguments); }, /** diff --git a/addons/web_editor/static/src/js/editor/rte.js b/addons/web_editor/static/src/js/editor/rte.js index c0e2218d974..6da2ea72ea1 100644 --- a/addons/web_editor/static/src/js/editor/rte.js +++ b/addons/web_editor/static/src/js/editor/rte.js @@ -405,7 +405,7 @@ var RTEWidget = Widget.extend({ var $el = $(el); $el.find('[class]').filter(function () { - if (!this.className.match(/\S/)) { + if (!this.getAttribute('class').match(/\S/)) { this.removeAttribute('class'); } }); diff --git a/addons/website/static/src/js/content/snippets.animation.js b/addons/website/static/src/js/content/snippets.animation.js index e5115ec7b18..f4f49271b87 100644 --- a/addons/website/static/src/js/content/snippets.animation.js +++ b/addons/website/static/src/js/content/snippets.animation.js @@ -592,16 +592,35 @@ registry.mediaVideo = Animation.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_editableMode_display"> </div>'; - var size = '<div class="media_iframe_video_size"> </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"> </div>' + + '<div class="media_iframe_video_size"> </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 eae57d4a6cf..7f05a55d26d 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -445,7 +445,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 42bac83468a..c70eea3c314 100644 --- a/addons/website_sale/views/templates.xml +++ b/addons/website_sale/views/templates.xml @@ -1055,6 +1055,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)"/> @@ -1088,7 +1089,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)"/> |
