diff options
| author | Christophe Simonis <chs@odoo.com> | 2019-08-29 16:45:15 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2019-08-29 16:45:15 +0200 |
| commit | 8bd6a93c74de7aa68b0a85cc6132aa22975462d8 (patch) | |
| tree | af6334a048dd1e2c03f3a937c03feacc5b462efd /addons | |
| parent | 3d6e91789968719c726420554d25b25f81282a55 (diff) | |
| parent | ede253f1b2edbd10a1df3991438262a4a47059c1 (diff) | |
[MERGE] forward port branch saas-11.3 up to ede253f1b2e
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/account/models/account.py | 2 | ||||
| -rw-r--r-- | addons/account/models/account_move.py | 2 | ||||
| -rw-r--r-- | addons/account/tests/test_reconciliation.py | 62 | ||||
| -rw-r--r-- | addons/account_check_printing/models/account_payment.py | 5 | ||||
| -rw-r--r-- | addons/account_check_printing/views/account_payment_views.xml | 1 | ||||
| -rw-r--r-- | addons/auth_oauth/controllers/main.py | 17 | ||||
| -rw-r--r-- | addons/gamification/views/goal.xml | 5 | ||||
| -rw-r--r-- | addons/hr_recruitment/views/hr_recruitment_views.xml | 1 | ||||
| -rw-r--r-- | addons/mail/static/src/js/utils.js | 7 | ||||
| -rw-r--r-- | addons/maintenance/views/maintenance_views.xml | 8 | ||||
| -rw-r--r-- | addons/web/static/src/js/fields/relational_fields.js | 2 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/graph/graph_view.js | 3 | ||||
| -rw-r--r-- | addons/web/static/src/js/widgets/auto_complete.js | 12 | ||||
| -rw-r--r-- | addons/web/static/tests/views/graph_tests.js | 21 | ||||
| -rw-r--r-- | addons/website/models/website.py | 7 | ||||
| -rw-r--r-- | addons/website_event_sale/models/sale_order.py | 5 | ||||
| -rw-r--r-- | addons/website_event_track/models/event_track.py | 2 |
17 files changed, 132 insertions, 30 deletions
diff --git a/addons/account/models/account.py b/addons/account/models/account.py index c4569e91886..48185ea1b1c 100644 --- a/addons/account/models/account.py +++ b/addons/account/models/account.py @@ -824,7 +824,7 @@ class AccountJournal(models.Model): @api.depends('company_id') def _belong_to_company(self): for journal in self: - journal.belong_to_company = (journal.company_id.id == self.env.user.company_id.id) + journal.belongs_to_company = (journal.company_id.id == self.env.user.company_id.id) @api.multi def _search_company_journals(self, operator, value): diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index edb8f4849a1..b2125d4eb4c 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -541,7 +541,7 @@ class AccountMoveLine(models.Model): else: date = partial_line.credit_move_id.date if partial_line.debit_move_id == line else partial_line.debit_move_id.date rate = line.currency_id.with_context(date=date).rate - amount_residual_currency += sign_partial_line * partial_line.amount * rate + amount_residual_currency += sign_partial_line * line.currency_id.round(partial_line.amount * rate) #computing the `reconciled` field. reconciled = False diff --git a/addons/account/tests/test_reconciliation.py b/addons/account/tests/test_reconciliation.py index e9b494b385e..28ce8f054f1 100644 --- a/addons/account/tests/test_reconciliation.py +++ b/addons/account/tests/test_reconciliation.py @@ -1181,6 +1181,68 @@ class TestReconciliationExec(TestReconciliation): self.assertEqual(invoice_cust_1.state, 'open', 'Invoice is in status %s' % invoice_cust_1.state) + def test_inv_refund_foreign_payment_writeoff_domestic(self): + company = self.env.ref('base.main_company') + self.env['res.currency.rate'].search([]).unlink() + self.env['res.currency.rate'].create({ + 'name': time.strftime('%Y') + '-07-01', + 'rate': 1.0, + 'currency_id': self.currency_euro_id, + 'company_id': company.id + }) + self.env['res.currency.rate'].create({ + 'name': time.strftime('%Y') + '-07-01', + 'rate': 1.113900, # Don't change this ! + 'currency_id': self.currency_usd_id, + 'company_id': self.env.ref('base.main_company').id + }) + inv1 = self.create_invoice(invoice_amount=480, currency_id=self.currency_usd_id) + inv2 = self.create_invoice(type="out_refund", invoice_amount=140, currency_id=self.currency_usd_id) + + payment = self.env['account.payment'].create({ + 'payment_method_id': self.inbound_payment_method.id, + 'payment_type': 'inbound', + 'partner_type': 'customer', + 'partner_id': inv1.partner_id.id, + 'amount': 287.20, + 'journal_id': self.bank_journal_euro.id, + 'company_id': company.id, + }) + payment.post() + + inv1_receivable = inv1.move_id.line_ids.filtered(lambda l: l.account_id.internal_type == 'receivable') + inv2_receivable = inv2.move_id.line_ids.filtered(lambda l: l.account_id.internal_type == 'receivable') + pay_receivable = payment.move_line_ids.filtered(lambda l: l.account_id.internal_type == 'receivable') + + data_for_reconciliation = [ + { + 'type': 'partner', + 'id': inv1.partner_id.id, + 'mv_line_ids': (inv1_receivable + inv2_receivable + pay_receivable).ids, + 'new_mv_line_dicts': [ + { + 'credit': 20.09, # 18.04 in foreign currency + 'debit': 0.00, + 'journal_id': self.bank_journal_euro.id, + 'name': 'Total WriteOff (Fees)', + 'account_id': self.diff_expense_account.id + } + ] + } + ] + + self.env["account.reconciliation.widget"].process_move_lines(data_for_reconciliation) + + self.assertTrue(inv1_receivable.full_reconcile_id.exists()) + self.assertEquals(inv1_receivable.full_reconcile_id, inv2_receivable.full_reconcile_id) + self.assertEquals(inv1_receivable.full_reconcile_id, pay_receivable.full_reconcile_id) + + self.assertTrue(inv1.reconciled) + self.assertTrue(inv2.reconciled) + + self.assertEquals(inv1.state, 'paid') + self.assertEquals(inv2.state, 'paid') + def test_multiple_term_reconciliation_opw_1906665(self): '''Test that when registering a payment to an invoice with multiple payment term lines the reconciliation happens against the line diff --git a/addons/account_check_printing/models/account_payment.py b/addons/account_check_printing/models/account_payment.py index 882cf796db0..c706502985b 100644 --- a/addons/account_check_printing/models/account_payment.py +++ b/addons/account_check_printing/models/account_payment.py @@ -115,6 +115,11 @@ class AccountPayment(models.Model): """ This method is a hook for l10n_xx_check_printing modules to implement actual check printing capabilities """ raise UserError(_("You have to choose a check layout. For this, go in Apps, search for 'Checks layout' and install one.")) + + def set_check_amount_in_words(self): + for payment in self: + payment.check_amount_in_words = payment.currency_id.amount_to_text(payment.amount) if payment.currency_id else '' + ####################### #CHECK PRINTING METHODS ####################### diff --git a/addons/account_check_printing/views/account_payment_views.xml b/addons/account_check_printing/views/account_payment_views.xml index 56e3944b9d7..596449f9474 100644 --- a/addons/account_check_printing/views/account_payment_views.xml +++ b/addons/account_check_printing/views/account_payment_views.xml @@ -8,6 +8,7 @@ <xpath expr="//button[@name='post']" position="before"> <button name="print_checks" class="oe_highlight" attrs="{'invisible': ['|', ('payment_method_code', '!=', 'check_printing'), ('state', '!=', 'posted')]}" string="Print Check" type="object"/> <button name="unmark_sent" attrs="{'invisible': ['|', ('payment_method_code', '!=', 'check_printing'), ('state', '!=', 'sent')]}" string="Unmark Sent" type="object"/> + <button name="set_check_amount_in_words" attrs="{'invisible': ['|', ('payment_method_code', '!=', 'check_printing'), ('check_amount_in_words', '!=', False)]}" string="Reset Amount in Words" type="object" groups="base.group_no_one"/> </xpath> <xpath expr="//div[@name='amount_div']" position="after"> <field name="check_amount_in_words" attrs="{'invisible': [('payment_method_code', '!=', 'check_printing')], 'readonly': [('state', '!=', 'draft')]}" groups="base.group_no_one"/> diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py index 3b300070929..00eea3268b6 100644 --- a/addons/auth_oauth/controllers/main.py +++ b/addons/auth_oauth/controllers/main.py @@ -109,19 +109,10 @@ class OAuthLogin(Home): return response - @http.route() - def web_auth_signup(self, *args, **kw): - providers = self.list_providers() - response = super(OAuthLogin, self).web_auth_signup(*args, **kw) - response.qcontext.update(providers=providers) - return response - - @http.route() - def web_auth_reset_password(self, *args, **kw): - providers = self.list_providers() - response = super(OAuthLogin, self).web_auth_reset_password(*args, **kw) - response.qcontext.update(providers=providers) - return response + def get_auth_signup_qcontext(self): + result = super(OAuthLogin, self).get_auth_signup_qcontext() + result["providers"] = self.list_providers() + return result class OAuthController(http.Controller): diff --git a/addons/gamification/views/goal.xml b/addons/gamification/views/goal.xml index a3386496a47..da625c5eb51 100644 --- a/addons/gamification/views/goal.xml +++ b/addons/gamification/views/goal.xml @@ -135,6 +135,7 @@ <field name="completeness"/> <field name="state"/> <field name="target_goal"/> + <field name="definition_description"/> <field name="definition_condition"/> <field name="definition_suffix"/> <field name="definition_display"/> @@ -143,7 +144,9 @@ <field name="last_update"/> <templates> <t t-name="kanban-tooltip"> - <field name="definition_description"/> + <ul class="oe_kanban_tooltip"> + <li><t t-esc="record.definition_description.value" /></li> + </ul> </t> <t t-name="kanban-box"> <div t-attf-class="oe_kanban_card o_kanban_gamification #{record.end_date.raw_value < record.last_update.raw_value & record.state.raw_value == 'failed' ? 'oe_kanban_color_2' : ''} #{record.end_date.raw_value < record.last_update.raw_value & record.state.raw_value == 'reached' ? 'oe_kanban_color_5' : ''}"> diff --git a/addons/hr_recruitment/views/hr_recruitment_views.xml b/addons/hr_recruitment/views/hr_recruitment_views.xml index 5fa6424e959..2d81b4a6297 100644 --- a/addons/hr_recruitment/views/hr_recruitment_views.xml +++ b/addons/hr_recruitment/views/hr_recruitment_views.xml @@ -277,6 +277,7 @@ <field name="user_email"/> <field name="partner_name"/> <field name="type_id"/> + <field name="partner_id"/> <field name="job_id"/> <field name="department_id"/> <field name="message_needaction_counter"/> diff --git a/addons/mail/static/src/js/utils.js b/addons/mail/static/src/js/utils.js index 740be8eb54d..3673dd2ab21 100644 --- a/addons/mail/static/src/js/utils.js +++ b/addons/mail/static/src/js/utils.js @@ -8,7 +8,12 @@ var _t = core._t; function parseAndTransform(htmlString, transformFunction) { var openToken = "OPEN" + Date.now(); var string = htmlString.replace(/</g, openToken); - var children = $('<div>').html(string).contents(); + var children; + try { + children = $('<div>').html(string).contents(); + } catch (e) { + children = $('<div>').html('<pre>' + string + '</pre>').contents(); + } return _parseAndTransform(children, transformFunction) .replace(new RegExp(openToken, "g"), "<"); } diff --git a/addons/maintenance/views/maintenance_views.xml b/addons/maintenance/views/maintenance_views.xml index 6d847f32290..84369193854 100644 --- a/addons/maintenance/views/maintenance_views.xml +++ b/addons/maintenance/views/maintenance_views.xml @@ -126,8 +126,8 @@ <templates> <t t-name="kanban-tooltip"> <ul class="oe_kanban_tooltip"> - <li><b>Category:</b> <field name="category_id"/></li> - <li><b>Request to:</b> <field name="user_id"/></li> + <li t-if="record.category_id.raw_value"><b>Category:</b> <t t-esc="record.category_id.value"/></li> + <li t-if="record.user_id.raw_value"><b>Request to:</b> <t t-esc="record.user_id.value"/></li> </ul> </t> <t t-name="kanban-box"> @@ -424,8 +424,8 @@ <templates> <t t-name="kanban-tooltip"> <ul class="oe_kanban_tooltip"> - <li><b>Serial Number:</b> <field name="serial_no"/></li> - <li><b>Model Number:</b> <field name="model"/></li> + <li t-if="record.serial_no.raw_value"><b>Serial Number:</b> <t t-esc="record.serial_no.value"/></li> + <li t-if="record.model.raw_value"><b>Model Number:</b> <t t-esc="record.model.value"/></li> </ul> </t> <t t-name="kanban-box"> diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index f1086f2a2d2..f591af6ddac 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -2308,7 +2308,7 @@ var FieldStatus = AbstractField.extend({ var FieldSelection = AbstractField.extend({ template: 'FieldSelection', specialData: "_fetchSpecialRelation", - supportedFieldTypes: ['selection', 'many2one'], + supportedFieldTypes: ['selection'], events: _.extend({}, AbstractField.prototype.events, { 'change': '_onChange', }), diff --git a/addons/web/static/src/js/views/graph/graph_view.js b/addons/web/static/src/js/views/graph/graph_view.js index a55da16c6da..ca6c5bdf44c 100644 --- a/addons/web/static/src/js/views/graph/graph_view.js +++ b/addons/web/static/src/js/views/graph/graph_view.js @@ -53,6 +53,9 @@ var GraphView = AbstractView.extend({ this.arch.children.forEach(function (field) { var fieldName = field.attrs.name; + if (fieldName === "id") { + return; + } var interval = field.attrs.interval; if (interval) { intervalMapping[fieldName] = interval; diff --git a/addons/web/static/src/js/widgets/auto_complete.js b/addons/web/static/src/js/widgets/auto_complete.js index a25dc0150f5..1821e555331 100644 --- a/addons/web/static/src/js/widgets/auto_complete.js +++ b/addons/web/static/src/js/widgets/auto_complete.js @@ -127,12 +127,22 @@ return Widget.extend({ var $item = self.make_list_item(result).appendTo($list); result.$el = $item; }); + // IE9 doesn't support addEventListener with option { once: true } + this.el.onmousemove = function (ev) { + self.$('li').each(function (index, li) { + li.onmouseenter = self.focus_element.bind(self, $(li)); + }); + var targetFocus = ev.target.tagName === 'LI' ? + ev.target : + ev.target.closest('li'); + self.focus_element($(targetFocus)); + self.el.onmousemove = null; + }; this.show(); }, make_list_item: function (result) { var self = this; var $li = $('<li>') - .hover(function () {self.focus_element($li);}) .mousedown(function (ev) { if (ev.button === 0) { // left button self.select(ev, {item: {facet: result.facet}}); diff --git a/addons/web/static/tests/views/graph_tests.js b/addons/web/static/tests/views/graph_tests.js index afa3ea9d0ef..cea1ce9fdd8 100644 --- a/addons/web/static/tests/views/graph_tests.js +++ b/addons/web/static/tests/views/graph_tests.js @@ -122,6 +122,27 @@ QUnit.module('Views', { graph.destroy(); }); + QUnit.test('field id not in groupBy', function (assert) { + assert.expect(1); + + var graph = createView({ + View: GraphView, + model: "foo", + data: this.data, + arch: '<graph string="Partners">' + + '<field name="id"/>' + + '</graph>', + mockRPC: function (route, args) { + if (args.method === 'read_group') { + assert.deepEqual(args.kwargs.groupby, [], + 'groupby should not contain id field'); + } + return this._super.apply(this, arguments); + } + }); + graph.destroy(); + }); + QUnit.test('switching mode', function (assert) { assert.expect(6); diff --git a/addons/website/models/website.py b/addons/website/models/website.py index 3b25ca5fcf4..62f4ff1db97 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -725,9 +725,6 @@ class Website(models.Model): domain_part, url = rule.build(value, append_unknown=False) if not query_string or query_string.lower() in url.lower(): page = {'loc': url} - for key, val in value.items(): - if key.startswith('__'): - page[key[2:]] = val if url in ('/sitemap.xml',): continue if url in url_set: @@ -751,9 +748,9 @@ class Website(models.Model): for page in pages: record = {'loc': page['url'], 'id': page['id'], 'name': page['name']} if page.view_id and page.view_id.priority != 16: - record['__priority'] = min(round(page.view_id.priority / 32.0, 1), 1) + record['priority'] = min(round(page.view_id.priority / 32.0, 1), 1) if page['write_date']: - record['__lastmod'] = page['write_date'].date() + record['lastmod'] = page['write_date'].date() yield record @api.multi diff --git a/addons/website_event_sale/models/sale_order.py b/addons/website_event_sale/models/sale_order.py index cd25e6e1943..c13e8a4c23e 100644 --- a/addons/website_event_sale/models/sale_order.py +++ b/addons/website_event_sale/models/sale_order.py @@ -41,7 +41,10 @@ class SaleOrder(models.Model): values['product_id'] = ticket.product_id.id values['event_id'] = ticket.event_id.id values['event_ticket_id'] = ticket.id - values['price_unit'] = ticket.price_reduce + if order.pricelist_id.discount_policy == 'without_discount': + values['price_unit'] = ticket.price + else: + values['price_unit'] = ticket.price_reduce values['name'] = ticket.get_ticket_multiline_description_sale() # avoid writing related values that end up locking the product record diff --git a/addons/website_event_track/models/event_track.py b/addons/website_event_track/models/event_track.py index 2f35e86bb0e..caeb64f8a84 100644 --- a/addons/website_event_track/models/event_track.py +++ b/addons/website_event_track/models/event_track.py @@ -160,7 +160,7 @@ class Track(models.Model): def message_get_suggested_recipients(self): recipients = super(Track, self).message_get_suggested_recipients() for track in self: - if track.partner_email != track.partner_id.email: + if track.partner_email and track.partner_email != track.partner_id.email: track._message_add_suggested_recipient(recipients, email=track.partner_email, reason=_('Speaker Email')) return recipients |
