diff options
| author | Christophe Simonis <chs@odoo.com> | 2017-10-02 13:05:17 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2017-10-02 13:05:17 +0200 |
| commit | 5ce21c7355b6f8f4c587f011417af3bcca7603a1 (patch) | |
| tree | acf66dcf1b1fd0e19b34e2d48bbd214a00b41abd /addons | |
| parent | abfac77a0644cad5eafe5a261b693ce4549bb0b5 (diff) | |
| parent | b3d0897f2d80352184874098d0f9fe2a6737d7a8 (diff) | |
[MERGE] forward port branch saas-16 up to b3d0897f2d8
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/account/static/src/js/reconciliation/reconciliation_model.js | 35 | ||||
| -rw-r--r-- | addons/calendar/models/calendar.py | 2 | ||||
| -rw-r--r-- | addons/calendar/tests/test_calendar.py | 44 | ||||
| -rw-r--r-- | addons/hr_payroll/models/hr_payslip.py | 8 | ||||
| -rw-r--r-- | addons/hr_payroll/models/hr_salary_rule.py | 4 | ||||
| -rw-r--r-- | addons/sale/views/sale_views.xml | 2 | ||||
| -rw-r--r-- | addons/web/static/tests/fields/relational_fields_tests.js | 47 | ||||
| -rw-r--r-- | addons/website_slides/models/slides.py | 3 |
8 files changed, 118 insertions, 27 deletions
diff --git a/addons/account/static/src/js/reconciliation/reconciliation_model.js b/addons/account/static/src/js/reconciliation/reconciliation_model.js index a16594d69cb..b35802422e4 100644 --- a/addons/account/static/src/js/reconciliation/reconciliation_model.js +++ b/addons/account/static/src/js/reconciliation/reconciliation_model.js @@ -717,26 +717,27 @@ var StatementModel = BasicModel.extend({ args: args, }) .then(function (result) { - var tax = result.taxes[0]; - var tax_prop = self._formatQuickCreate(line, { - 'link': prop.id, - 'tax_id': tax.id, - 'amount': tax.amount, - 'label': tax.name, - 'account_id': tax.account_id ? [tax.account_id, null] : prop.account_id, - 'analytic': tax.analytic, - 'is_tax': true, - '__focus': false - }); + _.each(result.taxes, function(tax){ + var tax_prop = self._formatQuickCreate(line, { + 'link': prop.id, + 'tax_id': tax.id, + 'amount': tax.amount, + 'label': tax.name, + 'account_id': tax.account_id ? [tax.account_id, null] : prop.account_id, + 'analytic': tax.analytic, + 'is_tax': true, + '__focus': false + }); - prop.amount = tax.base; - prop.amount_str = field_utils.format.monetary(Math.abs(prop.amount), {}, formatOptions); - prop.invalid = !self._isValid(prop); + prop.amount = tax.base; + prop.amount_str = field_utils.format.monetary(Math.abs(prop.amount), {}, formatOptions); + prop.invalid = !self._isValid(prop); - tax_prop.amount_str = field_utils.format.monetary(Math.abs(tax_prop.amount), {}, formatOptions); - tax_prop.invalid = prop.invalid; + tax_prop.amount_str = field_utils.format.monetary(Math.abs(tax_prop.amount), {}, formatOptions); + tax_prop.invalid = prop.invalid; - reconciliation_proposition.push(tax_prop); + reconciliation_proposition.push(tax_prop); + }); })); } else { var currencyData = { diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py index 6b061c6b79a..6de011b2915 100644 --- a/addons/calendar/models/calendar.py +++ b/addons/calendar/models/calendar.py @@ -1296,8 +1296,6 @@ class Meeting(models.Model): meeting_origin = self.browse(real_id) data = self.read(['allday', 'start', 'stop', 'rrule', 'duration'])[0] - data['start_date' if data['allday'] else 'start_datetime'] = data['start'] - data['stop_date' if data['allday'] else 'stop_datetime'] = data['stop'] if data.get('rrule'): data.update( values, diff --git a/addons/calendar/tests/test_calendar.py b/addons/calendar/tests/test_calendar.py index 5d3ffcc5e23..7fabe934a94 100644 --- a/addons/calendar/tests/test_calendar.py +++ b/addons/calendar/tests/test_calendar.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +import datetime from datetime import datetime, timedelta @@ -100,6 +101,49 @@ class TestCalendar(TransactionCase): self.assertEqual(calendar_event_sprint_review.byday, '1', 'rrule_type should be mothly') self.assertEqual(calendar_event_sprint_review.week_list, 'MO', 'rrule_type should be mothly') + def test_validation_error(self): + """ + Ideally this should build the base event in such a way that calling + write() triggers detach_recurring_event, but I've no idea how that + actually works so just calling it directly for now + """ + m = self.CalendarEvent.create({ + 'name': "wheee", + 'start': '2017-07-12 14:30:00', + 'allday': False, + 'rrule': u'FREQ=WEEKLY;BYDAY=WE;INTERVAL=1;COUNT=100', + 'duration': 0.5, + 'stop': '2017-07-12 15:00:00', + }) + + values = { + 'allday': False, + 'name': u'wheee', + 'attendee_ids': [ + (0, 0, {'state': u'needsAction', 'partner_id': 8, 'email': u'bob@example.com'}), + (0, 0, {'state': u'needsAction', 'partner_id': 10, 'email': u'ed@example.com'}), + ], + 'recurrency': True, + 'privacy': u'public', + 'stop': '2017-07-10 16:00:00', + 'alarm_ids': [(6, 0, [])], + 'start': '2017-07-10 15:30:00', + 'location': u"XXX", + 'duration': 0.5, + 'partner_ids': [(4, 10), (4, 8)], + 'description': u"A thing" + } + + records = m.detach_recurring_event(values) + self.assertEqual( + (m.start_datetime, m.stop_datetime), + (u'2017-07-12 14:30:00', u'2017-07-12 15:00:00'), + ) + self.assertEquals( + (records.start_datetime, records.stop_datetime), + (u'2017-07-10 15:30:00', u'2017-07-10 16:00:00'), + ) + def test_event_order(self): """ check the ordering of events when searching """ def create_event(name, date): diff --git a/addons/hr_payroll/models/hr_payslip.py b/addons/hr_payroll/models/hr_payslip.py index 562604a591d..3aaa01910ee 100644 --- a/addons/hr_payroll/models/hr_payslip.py +++ b/addons/hr_payroll/models/hr_payslip.py @@ -156,7 +156,7 @@ class HrPayslip(models.Model): # if we don't give the contract, then the rules to apply should be for all current contracts of the employee contract_ids = payslip.contract_id.ids or \ self.get_contract(payslip.employee_id, payslip.date_from, payslip.date_to) - lines = [(0, 0, line) for line in self.get_payslip_lines(contract_ids, payslip.id)] + lines = [(0, 0, line) for line in self._get_payslip_lines(contract_ids, payslip.id)] payslip.write({'line_ids': lines, 'number': number}) return True @@ -226,7 +226,7 @@ class HrPayslip(models.Model): return res @api.model - def get_payslip_lines(self, contract_ids, payslip_id): + def _get_payslip_lines(self, contract_ids, payslip_id): def _sum_salary_rule_category(localdict, category, amount): if category.parent_id: localdict = _sum_salary_rule_category(localdict, category.parent_id, amount) @@ -327,9 +327,9 @@ class HrPayslip(models.Model): localdict['result_qty'] = 1.0 localdict['result_rate'] = 100 #check if the rule can be applied - if rule.satisfy_condition(localdict) and rule.id not in blacklist: + if rule._satisfy_condition(localdict) and rule.id not in blacklist: #compute the amount of the rule - amount, qty, rate = rule.compute_rule(localdict) + amount, qty, rate = rule._compute_rule(localdict) #check if there is already a rule computed with that code previous_amount = rule.code in localdict and localdict[rule.code] or 0.0 #set/overwrite the amount computed for this rule in the localdict diff --git a/addons/hr_payroll/models/hr_salary_rule.py b/addons/hr_payroll/models/hr_salary_rule.py index cf1b01fa60c..5d6c49a0bf7 100644 --- a/addons/hr_payroll/models/hr_salary_rule.py +++ b/addons/hr_payroll/models/hr_salary_rule.py @@ -177,7 +177,7 @@ class HrSalaryRule(models.Model): #TODO should add some checks on the type of result (should be float) @api.multi - def compute_rule(self, localdict): + def _compute_rule(self, localdict): """ :param localdict: dictionary containing the environement in which to compute the rule :return: returns a tuple build as the base/amount computed, the quantity and the rate @@ -204,7 +204,7 @@ class HrSalaryRule(models.Model): raise UserError(_('Wrong python code defined for salary rule %s (%s).') % (self.name, self.code)) @api.multi - def satisfy_condition(self, localdict): + def _satisfy_condition(self, localdict): """ @param contract_id: id of hr.contract to be tested @return: returns True if the given rule match the condition for the given contract. Return False otherwise. diff --git a/addons/sale/views/sale_views.xml b/addons/sale/views/sale_views.xml index 09a4a37b1ce..32ef3464bae 100644 --- a/addons/sale/views/sale_views.xml +++ b/addons/sale/views/sale_views.xml @@ -185,7 +185,7 @@ <form string="Sales Order" class="o_sale_order"> <header> <button name="action_quotation_send" string="Send by Email" type="object" states="draft" class="btn-primary"/> - <button name="action_quotation_send" type="object" string="Send PRO-FORMA Invoice" groups="sale.group_proforma_sales" class="btn-primary" attrs="{'invisible': ['|', ('state', 'in', ['sent', 'sale']), ('invoice_count','>=',1)]}" context="{'proforma': True}"/> + <button name="action_quotation_send" type="object" string="Send PRO-FORMA Invoice" groups="sale.group_proforma_sales" class="btn-primary" attrs="{'invisible': ['|', ('state', '!=', 'draft'), ('invoice_count','>=',1)]}" context="{'proforma': True}"/> <button name="print_quotation" string="Print" type="object" states="draft" class="btn-primary o_sale_print"/> <button name="action_confirm" id="action_confirm" string="Confirm Sale" class="btn-primary" type="object" diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index bb7dc5db00e..0c910e5b4de 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -6791,6 +6791,53 @@ QUnit.module('relational_fields', { form.destroy(); }); + QUnit.test('many2many checkboxes with default values', function (assert) { + assert.expect(7); + + this.data.partner.fields.turtles.default = [3]; + this.data.partner.fields.turtles.type = "many2many"; + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch:'<form string="Partners">' + + '<field name="turtles" widget="many2many_checkboxes">' + + '</field>' + + '</form>', + mockRPC: function (route, args) { + if (args.method === 'create') { + assert.deepEqual(args.args[0].turtles, [[6, false, [1]]], + "correct values should have been sent to create"); + } + return this._super.apply(this, arguments); + } + }); + + assert.notOk(form.$('.o_checkbox input').eq(0).prop('checked'), + "first checkbox should not be checked"); + assert.notOk(form.$('.o_checkbox input').eq(1).prop('checked'), + "second checkbox should not be checked"); + assert.ok(form.$('.o_checkbox input').eq(2).prop('checked'), + "third checkbox should be checked"); + + form.$('.o_checkbox input:checked').click(); // Uncheck default record + form.$('.o_checkbox input').first().click(); // Check first record + form.$('.o_checkbox input').first().click(); // Uncheck first record + form.$('.o_checkbox input').first().click(); // Recheck first record + + assert.ok(form.$('.o_checkbox input').eq(0).prop('checked'), + "first checkbox should be checked"); + assert.notOk(form.$('.o_checkbox input').eq(1).prop('checked'), + "second checkbox should not be checked"); + assert.notOk(form.$('.o_checkbox input').eq(2).prop('checked'), + "third checkbox should not be checked"); + + form.$buttons.find('.o_form_button_save').click(); + + form.destroy(); + }); + QUnit.test('many2many list with x2many: add a record', function (assert) { assert.expect(18); diff --git a/addons/website_slides/models/slides.py b/addons/website_slides/models/slides.py index fbf48b596ad..b7632e96527 100644 --- a/addons/website_slides/models/slides.py +++ b/addons/website_slides/models/slides.py @@ -354,7 +354,7 @@ class Slide(models.Model): record.embed_code = '<iframe src="//www.youtube.com/embed/%s?theme=light" allowFullScreen="true" frameborder="0"></iframe>' % (record.document_id) else: # embed google doc video - record.embed_code = '<embed src="https://video.google.com/get_player?ps=docs&partnerid=30&docid=%s" type="application/x-shockwave-flash"></embed>' % (record.document_id) + record.embed_code = '<iframe src="//drive.google.com/file/d/%s/preview" allowFullScreen="true" frameborder="0"></iframe>' % (record.document_id) else: record.embed_code = False @@ -557,6 +557,7 @@ class Slide(models.Model): 'name': snippet['title'], 'image': self._fetch_data(snippet['thumbnails']['high']['url'], {}, 'image')['values'], 'description': snippet['description'], + 'mime_type': False, }) return {'values': values} |
