diff options
| author | Christophe Simonis <chs@odoo.com> | 2018-10-31 20:43:03 +0100 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2018-10-31 20:43:03 +0100 |
| commit | f6ca72b3ce9ecc9007ae5825d2c648e3b26b098e (patch) | |
| tree | 7f58a009d826366f4bfbdcefbba5ac4c687c997c /addons | |
| parent | c2bc3381508bfb002cb9af3c3b6655273f8c07d6 (diff) | |
| parent | 21eb31d804722912993f34105af9ee5f1a31e090 (diff) | |
[MERGE] forward port branch saas-11.3 up to 21eb31d8047
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/account/models/account_invoice.py | 2 | ||||
| -rw-r--r-- | addons/account/models/account_payment.py | 2 | ||||
| -rw-r--r-- | addons/account/tests/test_payment.py | 27 | ||||
| -rw-r--r-- | addons/l10n_ch/models/res_bank.py | 6 | ||||
| -rw-r--r-- | addons/l10n_ro/data/l10n_ro_chart_data.xml | 2 | ||||
| -rw-r--r-- | addons/l10n_vn/data/l10n_vn_chart_data.xml | 24 | ||||
| -rw-r--r-- | addons/mail/static/src/js/services/chat_manager.js | 4 | ||||
| -rw-r--r-- | addons/mail/static/src/js/thread_field.js | 6 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/basic/basic_model.js | 5 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/basic/basic_view.js | 8 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/kanban/kanban_controller.js | 2 | ||||
| -rw-r--r-- | addons/web/static/tests/fields/relational_fields_tests.js | 87 | ||||
| -rw-r--r-- | addons/web/static/tests/views/kanban_tests.js | 24 | ||||
| -rw-r--r-- | addons/website/models/website.py | 5 |
14 files changed, 157 insertions, 47 deletions
diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index b80f4890233..58626c1066e 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -107,7 +107,7 @@ class AccountInvoice(models.Model): def _compute_residual(self): residual = 0.0 residual_company_signed = 0.0 - sign = self.type in ['in_invoice', 'out_refund'] and -1 or 1 + sign = self.type in ['in_refund', 'out_refund'] and -1 or 1 for line in self.sudo().move_id.line_ids: if line.account_id == self.account_id: residual_company_signed += line.amount_residual diff --git a/addons/account/models/account_payment.py b/addons/account/models/account_payment.py index 646974d952e..dccf457a22a 100644 --- a/addons/account/models/account_payment.py +++ b/addons/account/models/account_payment.py @@ -198,7 +198,7 @@ class account_abstract_payment(models.AbstractModel): total = 0.0 groups = groupby(invoices, lambda i: i.currency_id) for payment_currency, payment_invoices in groups: - amount_total = sum(i.residual_signed for i in payment_invoices) + amount_total = sum([MAP_INVOICE_TYPE_PAYMENT_SIGN[i.type] * i.residual_signed for i in payment_invoices]) if payment_currency == currency: total += amount_total else: diff --git a/addons/account/tests/test_payment.py b/addons/account/tests/test_payment.py index 67883604d18..67350534347 100644 --- a/addons/account/tests/test_payment.py +++ b/addons/account/tests/test_payment.py @@ -464,31 +464,6 @@ class TestPayment(AccountingTestCase): #check the invoice status self.assertEqual(invoice.state, 'paid') - def test_payment_and_writeoff_out_refund(self): - # Use case: - # Company is in EUR, create a credit note for 100 EUR and register payment of 90. - # Mark invoice as fully paid with a write_off - # Check that all the aml are correctly created. - invoice = self.create_invoice(amount=100, type='out_refund', currency_id=self.currency_eur_id, partner=self.partner_agrolait.id) - # register payment on invoice - payment = self.payment_model.create({'payment_type': 'outbound', - 'payment_method_id': self.env.ref('account.account_payment_method_manual_in').id, - 'partner_type': 'customer', - 'partner_id': self.partner_agrolait.id, - 'amount': 90, - 'payment_date': time.strftime('%Y') + '-07-15', - 'payment_difference_handling': 'reconcile', - 'writeoff_account_id': self.account_payable.id, - 'journal_id': self.bank_journal_euro.id, - 'invoice_ids': [(4, invoice.id, None)] - }) - payment.post() - self.check_journal_items(payment.move_line_ids, [ - {'account_id': self.account_eur.id, 'debit': 0.0, 'credit': 90.0, 'amount_currency': 0.0, 'currency_id': False}, - {'account_id': self.account_payable.id, 'debit': 0.0, 'credit': 10.0, 'amount_currency': 0.0, 'currency_id': False}, - {'account_id': self.account_receivable.id, 'debit': 100.0, 'credit': 0.0, 'amount_currency': 0.0, 'currency_id': False}, - ]) - self.assertEqual(invoice.state, 'paid') def test_payment_and_writeoff_in_other_currency_3(self): # Use case related in revision 20935462a0cabeb45480ce70114ff2f4e91eaf79 @@ -537,4 +512,4 @@ class TestPayment(AccountingTestCase): # Check the invoice status and the full reconciliation: the difference on the receivable account # should have been completed by an exchange rate difference entry self.assertEqual(invoice.state, 'paid') - self.assertTrue(invoice.move_id.line_ids.filtered(lambda l: l.account_id == self.account_receivable)[0].full_reconcile_id) + self.assertTrue(invoice.move_id.line_ids.filtered(lambda l: l.account_id == self.account_receivable)[0].full_reconcile_id)
\ No newline at end of file diff --git a/addons/l10n_ch/models/res_bank.py b/addons/l10n_ch/models/res_bank.py index 8e3d9d4949d..90e9be09048 100644 --- a/addons/l10n_ch/models/res_bank.py +++ b/addons/l10n_ch/models/res_bank.py @@ -10,8 +10,12 @@ from odoo.tools.misc import mod10r def _is_l10n_ch_postal(account_ref): """ Returns True iff the string account_ref is a valid postal account number, i.e. it only contains ciphers and is last cipher is the result of a recursive - modulo 10 operation ran over the rest of it. + modulo 10 operation ran over the rest of it. Shorten form with - is also accepted. """ + if re.match('^[0-9]{2}-[0-9]{1,6}-[0-9]$', account_ref or ''): + ref_subparts = account_ref.split('-') + account_ref = ref_subparts[0] + ref_subparts[1].rjust(6,'0') + ref_subparts[2] + if re.match('\d+$', account_ref or ''): account_ref_without_check = account_ref[:-1] return mod10r(account_ref_without_check) == account_ref diff --git a/addons/l10n_ro/data/l10n_ro_chart_data.xml b/addons/l10n_ro/data/l10n_ro_chart_data.xml index c5cf25a68d5..0f7b3c646a8 100644 --- a/addons/l10n_ro/data/l10n_ro_chart_data.xml +++ b/addons/l10n_ro/data/l10n_ro_chart_data.xml @@ -1807,7 +1807,7 @@ </record> <record id="pcg_4661" model="account.account.template"> - <field name="name">>Datorii din operaţiuni de fiducie</field> + <field name="name">Datorii din operaţiuni de fiducie</field> <field name="code">4661</field> <field name="user_type_id" ref="account.data_account_type_current_liabilities"/> <field name="chart_template_id" ref="ro_chart_template"/> diff --git a/addons/l10n_vn/data/l10n_vn_chart_data.xml b/addons/l10n_vn/data/l10n_vn_chart_data.xml index 0748dd1531e..c643d8a38e5 100644 --- a/addons/l10n_vn/data/l10n_vn_chart_data.xml +++ b/addons/l10n_vn/data/l10n_vn_chart_data.xml @@ -81,8 +81,7 @@ <field name="reconcile" eval="False"/> <field name="user_type_id" ref="account.data_account_type_current_assets"/> <field name="chart_template_id" ref="vn_template"/> - <field name="name">Thuế GTGT được khấu trừ của hàng hóa, dịch vụ - </field> + <field name="name">Thuế GTGT được khấu trừ của hàng hóa, dịch vụ</field> </record> <record id="chart1332" model="account.account.template"> <field name="code">1332</field> @@ -140,7 +139,7 @@ </record> <record id="chart1388" model="account.account.template"> <field name="code">1388</field> - <field name="reconcile" eval="False"/> + <field name="reconcile" eval="True"/> <field name="user_type_id" ref="account.data_account_type_current_assets"/> <field name="chart_template_id" ref="vn_template"/> <field name="name">Phải thu khác</field> @@ -149,7 +148,7 @@ <record id="chart141" model="account.account.template"> <field name="code">141</field> - <field name="reconcile" eval="False"/> + <field name="reconcile" eval="True"/> <field name="user_type_id" ref="account.data_account_type_current_assets"/> <field name="chart_template_id" ref="vn_template"/> <field name="name">Tạm ứng</field> @@ -322,8 +321,7 @@ <field name="reconcile" eval="False"/> <field name="user_type_id" ref="account.data_account_type_non_current_assets"/> <field name="chart_template_id" ref="vn_template"/> - <field name="name">Cây lâu năm, súc vật làm việc và cho sản phẩm - </field> + <field name="name">Cây lâu năm, súc vật làm việc và cho sản phẩm</field> </record> <record id="chart2118" model="account.account.template"> <field name="code">2118</field> @@ -449,7 +447,7 @@ <field name="reconcile" eval="False"/> <field name="user_type_id" ref="account.data_account_type_non_current_assets"/> <field name="chart_template_id" ref="vn_template"/> - <field name="name">>Đầu tư vào công ty liên doanh</field> + <field name="name">Đầu tư vào công ty liên doanh</field> </record> @@ -459,7 +457,7 @@ <field name="reconcile" eval="False"/> <field name="user_type_id" ref="account.data_account_type_non_current_assets"/> <field name="chart_template_id" ref="vn_template"/> - <field name="name">>Đầu tư góp vốn vào đơn vị khác</field> + <field name="name">Đầu tư góp vốn vào đơn vị khác</field> </record> <record id="chart2288" model="account.account.template"> @@ -651,14 +649,14 @@ <record id="chart3341" model="account.account.template"> <field name="code">3341</field> - <field name="reconcile" eval="False"/> + <field name="reconcile" eval="True"/> <field name="user_type_id" ref="account.data_account_type_current_liabilities"/> <field name="chart_template_id" ref="vn_template"/> <field name="name">Phải trả công nhân viên</field> </record> <record id="chart3348" model="account.account.template"> <field name="code">3348</field> - <field name="reconcile" eval="False"/> + <field name="reconcile" eval="True"/> <field name="user_type_id" ref="account.data_account_type_current_liabilities"/> <field name="chart_template_id" ref="vn_template"/> <field name="name">Phải trả người lao động khác</field> @@ -677,7 +675,7 @@ <field name="reconcile" eval="False"/> <field name="user_type_id" ref="account.data_account_type_current_liabilities"/> <field name="chart_template_id" ref="vn_template"/> - <field name="name">Phải trả nội bộ về vốn kinh doanh </field> + <field name="name">Phải trả nội bộ về vốn kinh doanh</field> </record> <record id="chart3362" model="account.account.template"> @@ -763,7 +761,7 @@ </record> <record id="chart3388" model="account.account.template"> <field name="code">3388</field> - <field name="reconcile" eval="False"/> + <field name="reconcile" eval="True"/> <field name="user_type_id" ref="account.data_account_type_current_liabilities"/> <field name="chart_template_id" ref="vn_template"/> <field name="name">Phải trả, phải nộp khác</field> @@ -790,7 +788,7 @@ <field name="reconcile" eval="False"/> <field name="user_type_id" ref="account.data_account_type_current_liabilities"/> <field name="chart_template_id" ref="vn_template"/> - <field name="name">Trái phiếu </field> + <field name="name">Trái phiếu</field> </record> <record id="chart34311" model="account.account.template"> <field name="code">34311</field> diff --git a/addons/mail/static/src/js/services/chat_manager.js b/addons/mail/static/src/js/services/chat_manager.js index aecf41b1d4f..70db9c29ed5 100644 --- a/addons/mail/static/src/js/services/chat_manager.js +++ b/addons/mail/static/src/js/services/chat_manager.js @@ -516,7 +516,9 @@ var ChatManager = AbstractService.extend({ if ('ids' in options) { // get messages from their ids (chatter is the main use case) return this._fetchDocumentMessages(options.ids, options).then(function (result) { - self.markAsRead(options.ids); + if (options.shouldMarkAsRead) { + self.markAsRead(options.ids); + } return result; }); } diff --git a/addons/mail/static/src/js/thread_field.js b/addons/mail/static/src/js/thread_field.js index 6d036208eb2..bffa6817cf7 100644 --- a/addons/mail/static/src/js/thread_field.js +++ b/addons/mail/static/src/js/thread_field.js @@ -19,6 +19,7 @@ var ThreadField = AbstractField.extend({ init: function () { this._super.apply(this, arguments); this.msgIDs = this.value.res_ids; + this._markAsReadOnRender = true; // DO NOT FORWARD-PORT }, willStart: function () { return this.alive(this.call('chat_manager', 'isReady')); @@ -68,6 +69,7 @@ var ThreadField = AbstractField.extend({ this.msgIDs = this.value.res_ids; // the mail widgets being persistent, one need to update the res_id on reset this.res_id = record.res_id; + this._markAsReadOnRender = true; // DO NOT FORWARD-PORT }, //-------------------------------------------------------------------------- @@ -123,6 +125,10 @@ var ThreadField = AbstractField.extend({ var self = this; options = options || {}; options.ids = ids; + if (this._markAsReadOnRender) { + options.shouldMarkAsRead = true; + this._markAsReadOnRender = false; + } var fetch_def = this.dp.add(this.call('chat_manager', 'getMessages', options)); return fetch_def.then(function (raw_messages) { var isCreateMode = false; diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index c6575303342..59621521a0a 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -3606,11 +3606,12 @@ var BasicModel = AbstractModel.extend({ */ _postprocess: function (record, options) { var self = this; + var viewType = options && options.viewType || record.viewType; var defs = []; _.each(record.getFieldNames(options), function (name) { var field = record.fields[name]; - var fieldInfo = record.fieldsInfo[record.viewType][name] || {}; + var fieldInfo = record.fieldsInfo[viewType][name] || {}; var options = fieldInfo.options || {}; if (options.always_reload) { if (record.fields[name].type === 'many2one' && record.data[name]) { @@ -3619,7 +3620,7 @@ var BasicModel = AbstractModel.extend({ model: field.relation, method: 'name_get', args: [element.data.id], - context: self._getContext(record, {fieldName: name}), + context: self._getContext(record, {fieldName: name, viewType: viewType}), }) .then(function (result) { element.data.display_name = result[0][1]; diff --git a/addons/web/static/src/js/views/basic/basic_view.js b/addons/web/static/src/js/views/basic/basic_view.js index 7ab9ba0547d..f49ac63514b 100644 --- a/addons/web/static/src/js/views/basic/basic_view.js +++ b/addons/web/static/src/js/views/basic/basic_view.js @@ -150,6 +150,14 @@ var BasicView = AbstractView.extend({ } } } + // Many2one: context is not the same between the different views + // this means the result of a name_get could differ + if (fieldType === 'many2one') { + if (JSON.stringify(record.data[name].context) !== + JSON.stringify(fieldInfo.context)) { + fieldNames.push(name); + } + } } }); diff --git a/addons/web/static/src/js/views/kanban/kanban_controller.js b/addons/web/static/src/js/views/kanban/kanban_controller.js index b577bf0a10f..6b574efde1a 100644 --- a/addons/web/static/src/js/views/kanban/kanban_controller.js +++ b/addons/web/static/src/js/views/kanban/kanban_controller.js @@ -268,7 +268,7 @@ var KanbanController = BasicController.extend({ _onButtonNew: function () { var state = this.model.get(this.handle, {raw: true}); var quickCreateEnabled = this.quickCreateEnabled && viewUtils.isQuickCreateEnabled(state); - if (this.on_create === 'quick_create' && quickCreateEnabled) { + if (this.on_create === 'quick_create' && quickCreateEnabled && state.data.length) { // Activate the quick create in the first column this.renderer.addQuickCreate(); } else if (this.on_create && this.on_create !== 'quick_create') { diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index 20008a92c21..e9f08195ec1 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -380,6 +380,93 @@ QUnit.module('relational_fields', { form.destroy(); }); + QUnit.test('show_address works in a view embedded in a view of another type', function (assert) { + assert.expect(1); + + this.data.turtle.records[1].turtle_trululu = 2; + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '<form string="Partners">' + + '<field name="display_name"/>' + + '<field name="turtles"/>' + + '</form>', + res_id: 1, + archs: { + "turtle,false,form": '<form string="T">' + + '<field name="display_name"/>' + + '<field name="turtle_trululu" context="{\'show_address\': 1}" options="{\'always_reload\': True}"/>' + + '</form>', + "turtle,false,list": '<tree editable="bottom">' + + '<field name="display_name"/>' + + '</tree>', + }, + mockRPC: function (route, args) { + if (args.method === 'name_get') { + return this._super(route, args).then(function (result) { + if (args.model === 'partner' && args.kwargs.context.show_address) { + result[0][1] += '\nrue morgue\nparis 75013'; + } + return result; + }); + } + return this._super(route, args); + }, + }); + // click the turtle field, opens a modal with the turtle form view + form.$('.o_data_row:first td.o_data_cell').click(); + + assert.strictEqual($('[name="turtle_trululu"]').text(), "second recordrue morgueparis 75013", + "The partner's address should be displayed"); + form.destroy(); + }); + + QUnit.test('many2one data is reloaded if there is a context to take into account', function (assert) { + assert.expect(1); + + this.data.turtle.records[1].turtle_trululu = 2; + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '<form string="Partners">' + + '<field name="display_name"/>' + + '<field name="turtles"/>' + + '</form>', + res_id: 1, + archs: { + "turtle,false,form": '<form string="T">' + + '<field name="display_name"/>' + + '<field name="turtle_trululu" context="{\'show_address\': 1}" options="{\'always_reload\': True}"/>' + + '</form>', + "turtle,false,list": '<tree editable="bottom">' + + '<field name="display_name"/>' + + '<field name="turtle_trululu"/>' + + '</tree>', + }, + mockRPC: function (route, args) { + if (args.method === 'name_get') { + return this._super(route, args).then(function (result) { + if (args.model === 'partner' && args.kwargs.context.show_address) { + result[0][1] += '\nrue morgue\nparis 75013'; + } + return result; + }); + } + return this._super(route, args); + }, + }); + // click the turtle field, opens a modal with the turtle form view + form.$('.o_data_row:first').click(); + + assert.strictEqual($('.modal [name=turtle_trululu]').text(), "second recordrue morgueparis 75013", + "The partner's address should be displayed"); + form.destroy(); + }); + QUnit.test('many2ones in form views with search more', function (assert) { assert.expect(3); this.data.partner.records.push({ diff --git a/addons/web/static/tests/views/kanban_tests.js b/addons/web/static/tests/views/kanban_tests.js index d153d63ea2b..00a1f29cedc 100644 --- a/addons/web/static/tests/views/kanban_tests.js +++ b/addons/web/static/tests/views/kanban_tests.js @@ -4210,6 +4210,30 @@ QUnit.module('Views', { kanban.destroy(); }); + QUnit.test('quick_create on grouped kanban without column', function (assert) { + assert.expect(1); + this.data.partner.records = []; + var kanban = createView({ + View: KanbanView, + model: 'partner', + data: this.data, + arch: '<kanban class="o_kanban_test" on_create="quick_create"><templates><t t-name="kanban-box">' + + '<div>' + + '<field name="name"/>' + + '</div>' + + '</t></templates></kanban>', + groupBy: ['product_id'], + + intercepts: { + switch_view: function (event) { + assert.ok(true, "switch_view was called instead of quick_create"); + }, + }, + }); + kanban.$buttons.find('.o-kanban-button-new').click(); + kanban.destroy(); + }); + QUnit.test('keyboard navigation on kanban basic rendering', function (assert) { assert.expect(3); diff --git a/addons/website/models/website.py b/addons/website/models/website.py index 0b7e73e84af..92185307bae 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -72,6 +72,11 @@ class Website(models.Model): homepage_id = fields.Many2one('website.page', string='Homepage') favicon = fields.Binary(string="Website Favicon", help="This field holds the image used to display a favicon on the website.") + @api.onchange('language_ids') + def _onchange_language_ids(self): + if self.language_ids and self.default_lang_id not in self.language_ids: + self.default_lang_id = self.language_ids[0] + @api.multi def _compute_menu(self): Menu = self.env['website.menu'] |
