diff --git a/addons/bus/models/res_partner.py b/addons/bus/models/res_partner.py index b0b4c23d74ffcf4b74a975e64ddd11eedc640848..a476e0c08dcceccf414d6f716183248ab4b44adf 100644 --- a/addons/bus/models/res_partner.py +++ b/addons/bus/models/res_partner.py @@ -15,13 +15,14 @@ class ResPartner(models.Model): self.env.cr.execute(""" SELECT U.partner_id as id, - CASE WHEN age(now() AT TIME ZONE 'UTC', B.last_poll) > interval %s THEN 'offline' - WHEN age(now() AT TIME ZONE 'UTC', B.last_presence) > interval %s THEN 'away' + CASE WHEN age(now() AT TIME ZONE 'UTC', max(B.last_poll)) > interval %s THEN 'offline' + WHEN age(now() AT TIME ZONE 'UTC', max(B.last_presence)) > interval %s THEN 'away' ELSE 'online' END as status FROM bus_presence B JOIN res_users U ON B.user_id = U.id WHERE U.partner_id IN %s AND U.active = 't' + GROUP BY U.partner_id """, ("%s seconds" % DISCONNECTION_TIMER, "%s seconds" % AWAY_TIMER, tuple(self.ids))) res = dict(((status['id'], status['status']) for status in self.env.cr.dictfetchall())) for partner in self: diff --git a/addons/l10n_be_intrastat/wizard/xml_decl.py b/addons/l10n_be_intrastat/wizard/xml_decl.py index aaf67485a112a15dc47eaca5a9898d82b1778fc4..988f70716d2cbd8e3b711f9f565e2e1f0afdf1e1 100644 --- a/addons/l10n_be_intrastat/wizard/xml_decl.py +++ b/addons/l10n_be_intrastat/wizard/xml_decl.py @@ -102,35 +102,140 @@ class XmlDeclaration(models.TransientModel): 'res_id': self.id, } + def _build_intrastat_line(self, numlgn, item, linekey, amounts, dispatchmode, extendedmode): + self._set_Dim(item, 'EXSEQCODE', unicode(numlgn)) + self._set_Dim(item, 'EXTRF', unicode(linekey.EXTRF)) + self._set_Dim(item, 'EXCNT', unicode(linekey.EXCNT)) + self._set_Dim(item, 'EXTTA', unicode(linekey.EXTTA)) + self._set_Dim(item, 'EXREG', unicode(linekey.EXREG)) + self._set_Dim(item, 'EXTGO', unicode(linekey.EXGO)) + if extendedmode: + self._set_Dim(item, 'EXTPC', unicode(linekey.EXTPC)) + self._set_Dim(item, 'EXDELTRM', unicode(linekey.EXDELTRM)) + self._set_Dim(item, 'EXTXVAL', unicode(round(amounts[0], 0)).replace(".", ",")) + self._set_Dim(item, 'EXWEIGHT', unicode(round(amounts[1], 0)).replace(".", ",")) + self._set_Dim(item, 'EXUNITS', unicode(round(amounts[2], 0)).replace(".", ",")) + + def _get_intrastat_linekey(self, declcode, inv_line, dispatchmode, extendedmode): + IntrastatRegion = self.env['l10n_be_intrastat.region'] + company = self.company_id + + #Check type of transaction + if inv_line.intrastat_transaction_id: + extta = inv_line.intrastat_transaction_id.code + else: + extta = "1" + #Check country + if inv_line.invoice_id.intrastat_country_id: + excnt = inv_line.invoice_id.intrastat_country_id.code + else: + excnt = inv_line.invoice_id.partner_shipping_id.country_id.code or inv_line.invoice_id.partner_id.country_id.code + + #Check region + #If purchase, comes from purchase order, linked to a location, + #which is linked to the warehouse + #if sales, the sales order is linked to the warehouse + #if sales, from a delivery order, linked to a location, + #which is linked to the warehouse + #If none found, get the company one. + exreg = None + if inv_line.invoice_id.type in ('in_invoice', 'in_refund'): + #comes from purchase + po_lines = self.env['purchase.order.line'].search([('invoice_lines', 'in', inv_line.id)], limit=1) + if po_lines: + if self._is_situation_triangular(company, po_line=po_lines): + return + location = self.env['stock.location'].browse(po_lines.order_id._get_destination_location()) + region_id = self.env['stock.warehouse'].get_regionid_from_locationid(location) + if region_id: + exreg = IntrastatRegion.browse(region_id).code + elif inv_line.invoice_id.type in ('out_invoice', 'out_refund'): + #comes from sales + so_lines = self.env['sale.order.line'].search([('invoice_lines', 'in', inv_line.id)], limit=1) + if so_lines: + if self._is_situation_triangular(company, so_line=so_lines): + return + saleorder = so_lines.order_id + if saleorder and saleorder.warehouse_id and saleorder.warehouse_id.region_id: + exreg = IntrastatRegion.browse(saleorder.warehouse_id.region_id.id).code + + if not exreg: + if company.region_id: + exreg = company.region_id.code + else: + self._company_warning(_('The Intrastat Region of the selected company is not set, ' + 'please make sure to configure it first.')) + + #Check commodity codes + intrastat_id = inv_line.product_id.get_intrastat_recursively() + if intrastat_id: + exgo = self.env['report.intrastat.code'].browse(intrastat_id).name + else: + raise exceptions.Warning( + _('Product "%s" has no intrastat code, please configure it') % inv_line.product_id.display_name) + + #In extended mode, 2 more fields required + if extendedmode: + #Check means of transport + if inv_line.invoice_id.transport_mode_id: + extpc = inv_line.invoice_id.transport_mode_id.code + elif company.transport_mode_id: + extpc = company.transport_mode_id.code + else: + self._company_warning(_('The default Intrastat transport mode of your company ' + 'is not set, please make sure to configure it first.')) + + #Check incoterm + if inv_line.invoice_id.incoterm_id: + exdeltrm = inv_line.invoice_id.incoterm_id.code + elif company.incoterm_id: + exdeltrm = company.incoterm_id.code + else: + self._company_warning(_('The default Incoterm of your company is not set, ' + 'please make sure to configure it first.')) + else: + extpc = "" + exdeltrm = "" + intrastatkey = namedtuple("intrastatkey", + ['EXTRF', 'EXCNT', 'EXTTA', 'EXREG', + 'EXGO', 'EXTPC', 'EXDELTRM']) + return intrastatkey(EXTRF=declcode, EXCNT=excnt, + EXTTA=extta, EXREG=exreg, EXGO=exgo, + EXTPC=extpc, EXDELTRM=exdeltrm) + + def _get_reception_code(self, extended): + return 'EX19E' if extended else 'EX19S' + + def _get_reception_form(self, extended): + return 'EXF19E' if extended else 'EXF19S' + + def _get_expedition_code(self, extended): + return 'EX29E' if extended else 'EX29S' + + def _get_expedition_form(self, extended): + return 'EXF29E' if extended else 'EXF29S' + @api.multi def _get_lines(self, dispatchmode=False, extendedmode=False): company = self.company_id - IntrastatRegion = self.env['l10n_be_intrastat.region'] if dispatchmode: mode1 = 'out_invoice' mode2 = 'in_refund' - declcode = "29" + declcode = self._get_expedition_code(extendedmode) + declform = self._get_expedition_form(extendedmode) else: mode1 = 'in_invoice' mode2 = 'out_refund' - declcode = "19" + declcode = self._get_reception_code(extendedmode) + declform = self._get_reception_form(extendedmode) decl = ET.Element('Report') - if not extendedmode: - decl.set('code', 'EX%sS' % declcode) - else: - decl.set('code', 'EX%sE' % declcode) + decl.set('code', declcode) decl.set('date', '%s-%s' % (self.year, self.month)) datas = ET.SubElement(decl, 'Data') - if not extendedmode: - datas.set('form', 'EXF%sS' % declcode) - else: - datas.set('form', 'EXF%sE' % declcode) + datas.set('form', declform) datas.set('close', 'true') - intrastatkey = namedtuple("intrastatkey", - ['EXTRF', 'EXCNT', 'EXTTA', 'EXREG', - 'EXGO', 'EXTPC', 'EXDELTRM']) entries = {} query = """ @@ -166,86 +271,10 @@ class XmlDeclaration(models.TransientModel): invoicelines = self.env['account.invoice.line'].browse(invoicelines_ids) for inv_line in invoicelines: + linekey = self._get_intrastat_linekey(declcode, inv_line, dispatchmode, extendedmode) + if linekey is None: + continue - #Check type of transaction - if inv_line.intrastat_transaction_id: - extta = inv_line.intrastat_transaction_id.code - else: - extta = "1" - #Check country - if inv_line.invoice_id.intrastat_country_id: - excnt = inv_line.invoice_id.intrastat_country_id.code - else: - excnt = inv_line.invoice_id.partner_shipping_id.country_id.code or inv_line.invoice_id.partner_id.country_id.code - - #Check region - #If purchase, comes from purchase order, linked to a location, - #which is linked to the warehouse - #if sales, the sales order is linked to the warehouse - #if sales, from a delivery order, linked to a location, - #which is linked to the warehouse - #If none found, get the company one. - exreg = None - if inv_line.invoice_id.type in ('in_invoice', 'in_refund'): - #comes from purchase - po_lines = self.env['purchase.order.line'].search([('invoice_lines', 'in', inv_line.id)], limit=1) - if po_lines: - if self._is_situation_triangular(company, po_line=po_lines): - continue - location = self.env['stock.location'].browse(po_lines.order_id._get_destination_location()) - region_id = self.env['stock.warehouse'].get_regionid_from_locationid(location) - if region_id: - exreg = IntrastatRegion.browse(region_id).code - elif inv_line.invoice_id.type in ('out_invoice', 'out_refund'): - #comes from sales - so_lines = self.env['sale.order.line'].search([('invoice_lines', 'in', inv_line.id)], limit=1) - if so_lines: - if self._is_situation_triangular(company, so_line=so_lines): - continue - saleorder = so_lines.order_id - if saleorder and saleorder.warehouse_id and saleorder.warehouse_id.region_id: - exreg = IntrastatRegion.browse(saleorder.warehouse_id.region_id.id).code - - if not exreg: - if company.region_id: - exreg = company.region_id.code - else: - self._company_warning(_('The Intrastat Region of the selected company is not set, ' - 'please make sure to configure it first.')) - - #Check commodity codes - intrastat_id = inv_line.product_id.get_intrastat_recursively() - if intrastat_id: - exgo = self.env['report.intrastat.code'].browse(intrastat_id).name - else: - raise exceptions.Warning( - _('Product "%s" has no intrastat code, please configure it') % inv_line.product_id.display_name) - - #In extended mode, 2 more fields required - if extendedmode: - #Check means of transport - if inv_line.invoice_id.transport_mode_id: - extpc = inv_line.invoice_id.transport_mode_id.code - elif company.transport_mode_id: - extpc = company.transport_mode_id.code - else: - self._company_warning(_('The default Intrastat transport mode of your company ' - 'is not set, please make sure to configure it first.')) - - #Check incoterm - if inv_line.invoice_id.incoterm_id: - exdeltrm = inv_line.invoice_id.incoterm_id.code - elif company.incoterm_id: - exdeltrm = company.incoterm_id.code - else: - self._company_warning(_('The default Incoterm of your company is not set, ' - 'please make sure to configure it first.')) - else: - extpc = "" - exdeltrm = "" - linekey = intrastatkey(EXTRF=declcode, EXCNT=excnt, - EXTTA=extta, EXREG=exreg, EXGO=exgo, - EXTPC=extpc, EXDELTRM=exdeltrm) #We have the key #calculate amounts if inv_line.price_unit and inv_line.quantity: @@ -269,18 +298,7 @@ class XmlDeclaration(models.TransientModel): continue numlgn += 1 item = ET.SubElement(datas, 'Item') - self._set_Dim(item, 'EXSEQCODE', unicode(numlgn)) - self._set_Dim(item, 'EXTRF', unicode(linekey.EXTRF)) - self._set_Dim(item, 'EXCNT', unicode(linekey.EXCNT)) - self._set_Dim(item, 'EXTTA', unicode(linekey.EXTTA)) - self._set_Dim(item, 'EXREG', unicode(linekey.EXREG)) - self._set_Dim(item, 'EXTGO', unicode(linekey.EXGO)) - if extendedmode: - self._set_Dim(item, 'EXTPC', unicode(linekey.EXTPC)) - self._set_Dim(item, 'EXDELTRM', unicode(linekey.EXDELTRM)) - self._set_Dim(item, 'EXTXVAL', unicode(round(amounts[0], 0)).replace(".", ",")) - self._set_Dim(item, 'EXWEIGHT', unicode(round(amounts[1], 0)).replace(".", ",")) - self._set_Dim(item, 'EXUNITS', unicode(round(amounts[2], 0)).replace(".", ",")) + self._build_intrastat_line(numlgn, item, linekey, amounts, dispatchmode, extendedmode) if numlgn == 0: #no datas diff --git a/addons/l10n_be_intrastat_2019/__init__.py b/addons/l10n_be_intrastat_2019/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..dc5e6b693d19dcacd224b7ab27b26f75e66cb7b2 --- /dev/null +++ b/addons/l10n_be_intrastat_2019/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import models diff --git a/addons/l10n_be_intrastat_2019/__manifest__.py b/addons/l10n_be_intrastat_2019/__manifest__.py new file mode 100644 index 0000000000000000000000000000000000000000..b3de01cd46b00521e89ee81c6da88280f1362d52 --- /dev/null +++ b/addons/l10n_be_intrastat_2019/__manifest__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +{ + 'name': 'Belgian Intrastat Declaration - Complement for 2019', + 'category': 'Accounting', + 'description': """ +Adds the possibility to specify the origin country of goods and the partner VAT in the Intrastat XML report. + """, + 'depends': ['l10n_be_intrastat'], + 'data': [ + 'views/account_invoice_line_view.xml', + ], + 'auto_install': True, +} diff --git a/addons/l10n_be_intrastat_2019/i18n/l10n_be_intrastat_2019.pot b/addons/l10n_be_intrastat_2019/i18n/l10n_be_intrastat_2019.pot new file mode 100644 index 0000000000000000000000000000000000000000..5953a7be43c00b435f68a2bb5c8570bb2448f5b0 --- /dev/null +++ b/addons/l10n_be_intrastat_2019/i18n/l10n_be_intrastat_2019.pot @@ -0,0 +1,32 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * l10n_be_intrastat_2019 +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-21 11:04+0000\n" +"PO-Revision-Date: 2019-01-21 11:04+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: l10n_be_intrastat_2019 +#: model:ir.model,name:l10n_be_intrastat_2019.model_l10n_be_intrastat_xml_xml_decl +msgid "Intrastat XML Declaration" +msgstr "" + +#. module: l10n_be_intrastat_2019 +#: model:ir.model,name:l10n_be_intrastat_2019.model_account_invoice_line +msgid "Invoice Line" +msgstr "" + +#. module: l10n_be_intrastat_2019 +#: model:ir.model.fields,field_description:l10n_be_intrastat_2019.field_account_invoice_line_intrastat_product_origin_country_id +msgid "Origin Country of Product" +msgstr "" + diff --git a/addons/l10n_be_intrastat_2019/models/__init__.py b/addons/l10n_be_intrastat_2019/models/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..9115b4d66b62291065062392be8677c6e8b76114 --- /dev/null +++ b/addons/l10n_be_intrastat_2019/models/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +from . import account_intrastat_report +from . import account_invoice_line diff --git a/addons/l10n_be_intrastat_2019/models/account_intrastat_report.py b/addons/l10n_be_intrastat_2019/models/account_intrastat_report.py new file mode 100644 index 0000000000000000000000000000000000000000..2a091901a26b6cc92fc35769eaf2792ca8c901fb --- /dev/null +++ b/addons/l10n_be_intrastat_2019/models/account_intrastat_report.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models +from collections import namedtuple + + +class XmlDeclaration(models.TransientModel): + """ + Intrastat XML Declaration + """ + _inherit = "l10n_be_intrastat_xml.xml_decl" + + def _build_intrastat_line(self, numlgn, item, linekey, amounts, dispatchmode, extendedmode): + super(XmlDeclaration, self)._build_intrastat_line(numlgn, item, linekey, amounts, dispatchmode, extendedmode) + if dispatchmode: + self._set_Dim(item, 'EXCNTORI', unicode(linekey.EXCNTORI)) + self._set_Dim(item, 'PARTNERID', unicode(linekey.PARTNERID)) + + def _get_intrastat_linekey(self, declcode, inv_line, dispatchmode, extendedmode): + res = super(XmlDeclaration, self)._get_intrastat_linekey(declcode, inv_line, dispatchmode, extendedmode) + if res and dispatchmode: + res_dict = res._asdict() + res_dict['EXCNTORI'] = inv_line.intrastat_product_origin_country_id.code or 'QU' + res_dict['PARTNERID'] = inv_line.invoice_id.partner_id.vat or 'QV999999999999' + return namedtuple('intrastatkey', res_dict.keys())(**res_dict) + return res + + def _get_expedition_code(self, extended): + return 'INTRASTAT_X_E' if extended else 'INTRASTAT_X_S' + + def _get_expedition_form(self, extended): + return 'INTRASTAT_X_EF' if extended else 'INTRASTAT_X_SF' diff --git a/addons/l10n_be_intrastat_2019/models/account_invoice_line.py b/addons/l10n_be_intrastat_2019/models/account_invoice_line.py new file mode 100644 index 0000000000000000000000000000000000000000..01199b0174aa82852b749e4fb5266ed1654e1eda --- /dev/null +++ b/addons/l10n_be_intrastat_2019/models/account_invoice_line.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, fields, models + +class AccountInvoiceLine(models.Model): + _inherit = 'account.invoice.line' + + intrastat_product_origin_country_id = fields.Many2one('res.country', string='Origin Country of Product') diff --git a/addons/l10n_be_intrastat_2019/views/account_invoice_line_view.xml b/addons/l10n_be_intrastat_2019/views/account_invoice_line_view.xml new file mode 100644 index 0000000000000000000000000000000000000000..187e32b161e8e0fa4fa7f52e0c4bd26a647f7550 --- /dev/null +++ b/addons/l10n_be_intrastat_2019/views/account_invoice_line_view.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <record id="invoice_line_be_intrastat_data_form" model="ir.ui.view"> + <field name="name">account.invoice.form.inherit.account.be.intrastat</field> + <field name="model">account.invoice</field> + <field name="inherit_id" ref="account.invoice_form"/> + <field name="arch" type="xml"> + <xpath expr="//field[@name='invoice_line_ids']//field[@name='quantity']" position="before"> + <field name="intrastat_product_origin_country_id" options="{'no_create_edit': True}"/> + </xpath> + </field> + </record> +</odoo> diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index ad0a327d591f2498bc93e25b6b28df6b7cd87ed3..a5c92708f6ae415b39f179588731eb5ed5b458a3 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -467,7 +467,7 @@ class SaleOrder(models.Model): order.state = 'sale' order.confirmation_date = fields.Datetime.now() if self.env.context.get('send_email'): - self.force_quotation_send() + order.force_quotation_send() order.order_line._action_procurement_create() if self.env['ir.values'].get_default('sale.config.settings', 'auto_done_setting'): self.action_done() diff --git a/addons/web/static/src/js/views/form_relational_widgets.js b/addons/web/static/src/js/views/form_relational_widgets.js index 2ca483eac2bb028d2a92f2cd496b8bae0eec1af5..1dd61553ca296cccbfaf0043aa013cbe978f5ee7 100644 --- a/addons/web/static/src/js/views/form_relational_widgets.js +++ b/addons/web/static/src/js/views/form_relational_widgets.js @@ -264,6 +264,12 @@ var FieldMany2One = common.AbstractField.extend(common.CompletionFieldMixin, com } }); + // avoid ignoring autocomplete="off" by obfuscating placeholder, see #30439 + if (this.$input.attr('placeholder')) { + this.$input.attr('placeholder', function (index, val) { + return val.split('').join('\ufeff'); + }); + } var isSelecting = false; // autocomplete this.$input.autocomplete({ diff --git a/doc/cla/corporate/levelprime.md b/doc/cla/corporate/levelprime.md index bca6d6aa7d9fd16532853e4ab5f990b20491604c..d2d579302d8761d51b155ec67ae9216af9004b58 100644 --- a/doc/cla/corporate/levelprime.md +++ b/doc/cla/corporate/levelprime.md @@ -9,9 +9,12 @@ declaration. Signed, Roberto Fichera roberto.fichera@levelprime.com https://github.com/robyf70 +Filippo Iovine - filippo.iovine@levelprime.com - https://github.com/FilippoIOVINE List of contributors: Roberto Fichera roberto.fichera@levelprime.com https://github.com/robyf70 Roberto Fichera robyf@tekno-soft.it https://github.com/robyf70 +Filippo Iovine - filippo.iovine@levelprime.com - https://github.com/FilippoIOVINE +Filippo Iovine - filippo.jovine@gmail.com - https://github.com/FilippoIOVINE diff --git a/odoo/addons/base/ir/ir_ui_view.py b/odoo/addons/base/ir/ir_ui_view.py index 6cd9fa8ec59245e00d97354b9ae98cfa74c3951b..275dc7d3490c39fddcfa91b0eee0f189f25530d1 100644 --- a/odoo/addons/base/ir/ir_ui_view.py +++ b/odoo/addons/base/ir/ir_ui_view.py @@ -362,7 +362,10 @@ actual arch. def _compute_defaults(self, values): if 'inherit_id' in values: - values.setdefault('mode', 'extension' if values['inherit_id'] else 'primary') + # Do not automatically change the mode if the view already has an inherit_id, + # and the user change it to another. + if not values['inherit_id'] or all(not view.inherit_id for view in self): + values.setdefault('mode', 'extension' if values['inherit_id'] else 'primary') return values @api.model diff --git a/odoo/addons/base/tests/test_views.py b/odoo/addons/base/tests/test_views.py index bd462932e5f2366ad95b336dc8aefdd4d2ebc90d..16b859464393fb98e76f7b796726ee5e7a3c9e14 100644 --- a/odoo/addons/base/tests/test_views.py +++ b/odoo/addons/base/tests/test_views.py @@ -905,6 +905,12 @@ class ViewModeField(ViewCase): }) self.assertEqual(view2.mode, 'extension') + view2.write({'inherit_id': None}) + self.assertEqual(view2.mode, 'primary') + + view2.write({'inherit_id': view.id}) + self.assertEqual(view2.mode, 'extension') + @mute_logger('odoo.sql_db') def testModeExplicit(self): view = self.View.create({ @@ -917,6 +923,7 @@ class ViewModeField(ViewCase): 'arch': '<qweb/>' }) self.assertEqual(view.mode, 'primary') + self.assertEqual(view2.mode, 'primary') with self.assertRaises(IntegrityError): self.View.create({ @@ -968,6 +975,27 @@ class ViewModeField(ViewCase): view.write({'mode': 'primary'}) + def testChangeInheritOfPrimary(self): + """ + A primary view with an inherit_id must remain primary when changing the inherit_id + """ + base1 = self.View.create({ + 'inherit_id': None, + 'arch': '<qweb/>', + }) + base2 = self.View.create({ + 'inherit_id': None, + 'arch': '<qweb/>', + }) + view = self.View.create({ + 'mode': 'primary', + 'inherit_id': base1.id, + 'arch': '<qweb/>', + }) + self.assertEqual(view.mode, 'primary') + view.write({'inherit_id': base2.id}) + self.assertEqual(view.mode, 'primary') + class TestDefaultView(ViewCase): def testDefaultViewBase(self):