def test_onchange_editable_compute_one2many(self): # create a record with a computed editable field ('edit') on lines record = self.env['test_new_api.compute_editable'].create({'line_ids': [(0, 0, {'value': 7})]}) self.env.flush_all() line = record.line_ids self.assertRecordValues(line, [{'value': 7, 'edit': 7, 'count': 0}]) # retrieve the onchange spec for calling 'onchange' spec = Form(record)._view['onchange'] # The onchange on 'line_ids' should increment 'count' and keep the value # of 'edit' (this field should not be recomputed), whatever the order of # the fields in the dictionary. This ensures that the value set by the # user on a computed editable field on a line is not lost. line_ids = [ Command.update(line.id, {'value': 8, 'edit': 9, 'count': 0}), Command.create({'value': 8, 'edit': 9, 'count': 0}), ] result = record.onchange({'line_ids': line_ids}, 'line_ids', spec) expected = {'value': { 'line_ids': [ Command.clear(), Command.update(line.id, {'value': 8, 'edit': 9, 'count': 8}), Command.create({'value': 8, 'edit': 9, 'count': 8}), ], }} self.assertEqual(result, expected) # change dict order in lines, and try again line_ids = [ (op, id_, dict(reversed(list(vals.items())))) for op, id_, vals in line_ids ] result = record.onchange({'line_ids': line_ids}, 'line_ids', spec) self.assertEqual(result, expected)
def test_104_res_partner_recursion_indirect_cycle(self): """ Indirect hacky write to create cycle in children """ p3b = self.p1.create({ 'name': 'Elmtree Grand-Child 1.2', 'parent_id': self.p2.id }) with self.assertRaises(ValidationError): self.p2.write({ 'child_ids': [ Command.update(self.p3.id, {'parent_id': p3b.id}), Command.update(p3b.id, {'parent_id': self.p3.id}) ] })
def test_onchange_one2many_with_domain_on_related_field(self): """ test the value of the one2many field when defined with a domain on a related field""" discussion = self.env.ref('test_new_api.discussion_0') demo = self.user_demo # mimic UI behaviour, so we get subfields # (we need at least subfield: 'important_emails.important') view_info = self.Discussion.get_view(self.env.ref('test_new_api.discussion_form').id, 'form') field_onchange = self.Discussion._onchange_spec(view_info=view_info) self.assertEqual(field_onchange.get('messages'), '1') BODY = "What a beautiful day!" USER = self.env.user # create standalone email email = self.EmailMessage.create({ 'discussion': discussion.id, 'name': "[%s] %s" % ('', USER.name), 'body': BODY, 'author': USER.id, 'important': False, 'email_to': demo.email, }) # check if server-side cache is working correctly self.env.cache.invalidate() self.assertIn(email, discussion.emails) self.assertNotIn(email, discussion.important_emails) email.important = True self.assertIn(email, discussion.important_emails) # check that when trigger an onchange, we don't reset important emails # (force `invalidate` as but appear in onchange only when we get a cache # miss) self.env.cache.invalidate() self.assertEqual(len(discussion.messages), 4) values = { 'name': "Foo Bar", 'moderator': demo.id, 'categories': [Command.link(cat.id) for cat in discussion.categories], 'messages': [Command.link(msg.id) for msg in discussion.messages], 'participants': [Command.link(usr.id) for usr in discussion.participants], 'important_messages': [Command.link(msg.id) for msg in discussion.important_messages], 'important_emails': [Command.link(eml.id) for eml in discussion.important_emails], } self.env.cache.invalidate() result = discussion.onchange(values, 'name', field_onchange) self.assertEqual( result['value']['important_emails'], [Command.clear(), Command.update(email.id, { 'name': u'[Foo Bar] %s' % USER.name, 'body': BODY, 'author': USER.name_get()[0], 'size': len(BODY), 'important': True, 'email_to': demo.email, })], )
def create_company(self): self.ensure_one() if self.company_name: # Create parent company values = dict(name=self.company_name, is_company=True, vat=self.vat) values.update(self._update_fields_values(self._address_fields())) new_company = self.create(values) # Set new company as my parent self.write({ 'parent_id': new_company.id, 'child_ids': [Command.update(partner_id, dict(parent_id=new_company.id)) for partner_id in self.child_ids.ids] }) return True
def test_write_4_one2many(self): """ Check that we can write on an inherited one2many field. """ box = self.env.ref('test_inherits.box_a') box.write({'line_ids': [Command.create({'name': 'Line 1'})]}) self.assertTrue(all(box.line_ids._ids)) self.assertEqual(box.line_ids.mapped('name'), ['Line 1']) self.assertEqual(box.line_ids, box.unit_id.line_ids) box.flush() box.invalidate_cache(['line_ids']) box.write({'line_ids': [Command.create({'name': 'Line 2'})]}) self.assertTrue(all(box.line_ids._ids)) self.assertEqual(box.line_ids.mapped('name'), ['Line 1', 'Line 2']) self.assertEqual(box.line_ids, box.unit_id.line_ids) box.flush() box.invalidate_cache(['line_ids']) box.write({'line_ids': [Command.update(box.line_ids[0].id, {'name': 'First line'})]}) self.assertTrue(all(box.line_ids._ids)) self.assertEqual(box.line_ids.mapped('name'), ['First line', 'Line 2']) self.assertEqual(box.line_ids, box.unit_id.line_ids)
def test_write_base_many2many(self): """ Write on many2many field. """ rec1 = self.env['test_performance.base'].create({'name': 'X'}) # create N tags on rec1: O(N) queries with self.assertQueryCount(4): rec1.invalidate_cache() rec1.write({'tag_ids': [Command.create({'name': 0})]}) self.assertEqual(len(rec1.tag_ids), 1) with self.assertQueryCount(14): rec1.invalidate_cache() rec1.write({ 'tag_ids': [Command.create({'name': val}) for val in range(1, 12)] }) self.assertEqual(len(rec1.tag_ids), 12) tags = rec1.tag_ids # update N tags: O(N) queries with self.assertQueryCount(3): rec1.invalidate_cache() rec1.write({ 'tag_ids': [Command.update(tag.id, {'name': 'X'}) for tag in tags[0]] }) self.assertEqual(rec1.tag_ids, tags) with self.assertQueryCount(3): rec1.invalidate_cache() rec1.write({ 'tag_ids': [Command.update(tag.id, {'name': 'X'}) for tag in tags[1:]] }) self.assertEqual(rec1.tag_ids, tags) # delete N tags: O(1) queries with self.assertQueryCount(__system__=8, demo=8): rec1.invalidate_cache() rec1.write( {'tag_ids': [Command.delete(tag.id) for tag in tags[0]]}) self.assertEqual(rec1.tag_ids, tags[1:]) with self.assertQueryCount(__system__=8, demo=8): rec1.invalidate_cache() rec1.write( {'tag_ids': [Command.delete(tag.id) for tag in tags[1:]]}) self.assertFalse(rec1.tag_ids) self.assertFalse(tags.exists()) rec1.write( {'tag_ids': [Command.create({'name': val}) for val in range(12)]}) tags = rec1.tag_ids # unlink N tags: O(1) queries with self.assertQueryCount(3): rec1.invalidate_cache() rec1.write( {'tag_ids': [Command.unlink(tag.id) for tag in tags[0]]}) self.assertEqual(rec1.tag_ids, tags[1:]) with self.assertQueryCount(3): rec1.invalidate_cache() rec1.write( {'tag_ids': [Command.unlink(tag.id) for tag in tags[1:]]}) self.assertFalse(rec1.tag_ids) self.assertTrue(tags.exists()) rec2 = self.env['test_performance.base'].create({'name': 'X'}) # link N tags from rec1 to rec2: O(1) queries with self.assertQueryCount(3): rec1.invalidate_cache() rec2.write({'tag_ids': [Command.link(tag.id) for tag in tags[0]]}) self.assertEqual(rec2.tag_ids, tags[0]) with self.assertQueryCount(3): rec1.invalidate_cache() rec2.write({'tag_ids': [Command.link(tag.id) for tag in tags[1:]]}) self.assertEqual(rec2.tag_ids, tags) with self.assertQueryCount(2): rec1.invalidate_cache() rec2.write({'tag_ids': [Command.link(tag.id) for tag in tags[1:]]}) self.assertEqual(rec2.tag_ids, tags) # empty N tags in rec2: O(1) queries with self.assertQueryCount(3): rec1.invalidate_cache() rec2.write({'tag_ids': [Command.clear()]}) self.assertFalse(rec2.tag_ids) self.assertTrue(tags.exists()) with self.assertQueryCount(2): rec1.invalidate_cache() rec2.write({'tag_ids': [Command.clear()]}) self.assertFalse(rec2.tag_ids) # set N tags in rec2: O(1) queries with self.assertQueryCount(3): rec1.invalidate_cache() rec2.write({'tag_ids': [Command.set(tags.ids)]}) self.assertEqual(rec2.tag_ids, tags) with self.assertQueryCount(3): rec1.invalidate_cache() rec2.write({'tag_ids': [Command.set(tags[:8].ids)]}) self.assertEqual(rec2.tag_ids, tags[:8]) with self.assertQueryCount(4): rec1.invalidate_cache() rec2.write({'tag_ids': [Command.set(tags[4:].ids)]}) self.assertEqual(rec2.tag_ids, tags[4:]) with self.assertQueryCount(3): rec1.invalidate_cache() rec2.write({'tag_ids': [Command.set(tags.ids)]}) self.assertEqual(rec2.tag_ids, tags) with self.assertQueryCount(2): rec1.invalidate_cache() rec2.write({'tag_ids': [Command.set(tags.ids)]}) self.assertEqual(rec2.tag_ids, tags)
def test_write_base_one2many(self): """ Write on one2many field. """ rec1 = self.env['test_performance.base'].create({'name': 'X'}) # create N lines on rec1: O(N) queries with self.assertQueryCount(3): rec1.invalidate_cache() rec1.write({'line_ids': [Command.create({'value': 0})]}) self.assertEqual(len(rec1.line_ids), 1) with self.assertQueryCount(15): rec1.invalidate_cache() rec1.write({ 'line_ids': [Command.create({'value': val}) for val in range(1, 12)] }) self.assertEqual(len(rec1.line_ids), 12) lines = rec1.line_ids # update N lines: O(N) queries with self.assertQueryCount(6): rec1.invalidate_cache() rec1.write({ 'line_ids': [Command.update(line.id, {'value': 42}) for line in lines[0]] }) self.assertEqual(rec1.line_ids, lines) with self.assertQueryCount(26): rec1.invalidate_cache() rec1.write({ 'line_ids': [ Command.update(line.id, {'value': 42 + line.id}) for line in lines[1:] ] }) self.assertEqual(rec1.line_ids, lines) # delete N lines: O(1) queries with self.assertQueryCount(14): rec1.invalidate_cache() rec1.write( {'line_ids': [Command.delete(line.id) for line in lines[0]]}) self.assertEqual(rec1.line_ids, lines[1:]) with self.assertQueryCount(12): rec1.invalidate_cache() rec1.write( {'line_ids': [Command.delete(line.id) for line in lines[1:]]}) self.assertFalse(rec1.line_ids) self.assertFalse(lines.exists()) rec1.write({ 'line_ids': [Command.create({'value': val}) for val in range(12)] }) lines = rec1.line_ids # unlink N lines: O(1) queries with self.assertQueryCount(14): rec1.invalidate_cache() rec1.write( {'line_ids': [Command.unlink(line.id) for line in lines[0]]}) self.assertEqual(rec1.line_ids, lines[1:]) with self.assertQueryCount(12): rec1.invalidate_cache() rec1.write( {'line_ids': [Command.unlink(line.id) for line in lines[1:]]}) self.assertFalse(rec1.line_ids) self.assertFalse(lines.exists()) rec1.write({ 'line_ids': [Command.create({'value': val}) for val in range(12)] }) lines = rec1.line_ids rec2 = self.env['test_performance.base'].create({'name': 'X'}) # link N lines from rec1 to rec2: O(1) queries with self.assertQueryCount(8): rec1.invalidate_cache() rec2.write( {'line_ids': [Command.link(line.id) for line in lines[0]]}) self.assertEqual(rec1.line_ids, lines[1:]) self.assertEqual(rec2.line_ids, lines[0]) with self.assertQueryCount(8): rec1.invalidate_cache() rec2.write( {'line_ids': [Command.link(line.id) for line in lines[1:]]}) self.assertFalse(rec1.line_ids) self.assertEqual(rec2.line_ids, lines) with self.assertQueryCount(4): rec1.invalidate_cache() rec2.write( {'line_ids': [Command.link(line.id) for line in lines[0]]}) self.assertEqual(rec2.line_ids, lines) with self.assertQueryCount(4): rec1.invalidate_cache() rec2.write( {'line_ids': [Command.link(line.id) for line in lines[1:]]}) self.assertEqual(rec2.line_ids, lines) # empty N lines in rec2: O(1) queries with self.assertQueryCount(13): rec1.invalidate_cache() rec2.write({'line_ids': [Command.clear()]}) self.assertFalse(rec2.line_ids) with self.assertQueryCount(3): rec1.invalidate_cache() rec2.write({'line_ids': [Command.clear()]}) self.assertFalse(rec2.line_ids) rec1.write({ 'line_ids': [Command.create({'value': val}) for val in range(12)] }) lines = rec1.line_ids # set N lines in rec2: O(1) queries with self.assertQueryCount(8): rec1.invalidate_cache() rec2.write({'line_ids': [Command.set(lines[0].ids)]}) self.assertEqual(rec1.line_ids, lines[1:]) self.assertEqual(rec2.line_ids, lines[0]) with self.assertQueryCount(6): rec1.invalidate_cache() rec2.write({'line_ids': [Command.set(lines.ids)]}) self.assertFalse(rec1.line_ids) self.assertEqual(rec2.line_ids, lines) with self.assertQueryCount(4): rec1.invalidate_cache() rec2.write({'line_ids': [Command.set(lines.ids)]}) self.assertEqual(rec2.line_ids, lines)
def _str_to_one2many(self, model, field, records): name_create_enabled_fields = self._context.get( 'name_create_enabled_fields') or {} prefix = field.name + '/' relative_name_create_enabled_fields = { k[len(prefix):]: v for k, v in name_create_enabled_fields.items() if k.startswith(prefix) } commands = [] warnings = [] if len(records) == 1 and exclude_ref_fields(records[0]) == {}: # only one row with only ref field, field=ref1,ref2,ref3 as in # m2o/m2m record = records[0] subfield, ws = self._referencing_subfield(record) warnings.extend(ws) # transform [{subfield:ref1,ref2,ref3}] into # [{subfield:ref1},{subfield:ref2},{subfield:ref3}] records = ({ subfield: item } for item in record[subfield].split(',')) def log(f, exception): if not isinstance(exception, Warning): current_field_name = self.env[ field.comodel_name]._fields[f].string arg0 = exception.args[0] % { 'field': '%(field)s/' + current_field_name } exception.args = (arg0, *exception.args[1:]) raise exception warnings.append(exception) # Complete the field hierarchy path # E.g. For "parent/child/subchild", field hierarchy path for "subchild" is ['parent', 'child'] parent_fields_hierarchy = self._context.get('parent_fields_hierarchy', []) + [field.name] convert = self.with_context( name_create_enabled_fields=relative_name_create_enabled_fields, parent_fields_hierarchy=parent_fields_hierarchy).for_model( self.env[field.comodel_name]) for record in records: id = None refs = only_ref_fields(record) writable = convert(exclude_ref_fields(record), log) if refs: subfield, w1 = self._referencing_subfield(refs) warnings.extend(w1) try: id, _, w2 = self.db_id_for(model, field, subfield, record[subfield]) warnings.extend(w2) except ValueError: if subfield != 'id': raise writable['id'] = record['id'] if id: commands.append(Command.link(id)) commands.append(Command.update(id, writable)) else: commands.append(Command.create(writable)) return commands, warnings
def test_event_create_wtype(self): """ Test a single event creation with a type defining all sub records. """ event_type = self.env['event.type'].browse(self.test_event_type.ids) event_values = dict( self.event_base_vals, event_type_id=event_type.id, ) event = self.env['event.event'].create([event_values]) event.write({ 'event_ticket_ids': [ Command.update( event.event_ticket_ids[0].id, { 'start_sale_datetime': self.reference_now + timedelta(hours=1) }, ), Command.update( event.event_ticket_ids[1].id, { 'start_sale_datetime': self.reference_now + timedelta(hours=2) }, ) ], }) # check result self.assertEqual(event.address_id, self.env.user.company_id.partner_id) self.assertTrue(event.auto_confirm) self.assertEqual(event.country_id, self.env.user.company_id.country_id) self.assertEqual(event.date_tz, 'Europe/Paris') self.assertEqual(event.event_booth_count, 4) self.assertEqual(len(event.event_mail_ids), 3) self.assertEqual(len(event.event_ticket_ids), 2) self.assertTrue(event.introduction_menu) self.assertTrue(event.location_menu) self.assertTrue(event.menu_register_cta) self.assertEqual( event.message_partner_ids, self.env.user.partner_id + self.env.user.company_id.partner_id) self.assertEqual(event.note, '<p>Template note</p>') self.assertTrue(event.register_menu) self.assertEqual(len(event.question_ids), 3) self.assertTrue(event.seats_limited) self.assertEqual(event.seats_max, 30) self.assertEqual(event.stage_id, self.stage_def) self.assertEqual(event.tag_ids, self.tags) self.assertTrue(event.website_menu) # check time dependent computation: before event with freeze_time(self.reference_now): self.assertFalse(event.is_finished) self.assertFalse(event.is_ongoing) self.assertFalse(event.event_registrations_started) # check time dependent computation: registrations started with freeze_time(self.reference_now + timedelta(hours=1)): event.invalidate_model( ['is_finished', 'is_ongoing', 'event_registrations_started']) self.assertFalse(event.is_finished) self.assertFalse(event.is_ongoing) self.assertTrue(event.event_registrations_started) # check time dependent computation: during event with freeze_time(self.reference_now + timedelta(days=1, hours=1)): event.invalidate_model( ['is_finished', 'is_ongoing', 'event_registrations_started']) self.assertFalse(event.is_finished) self.assertTrue(event.is_ongoing) self.assertTrue(event.event_registrations_started)
def test_affect_base_amount_1(self): tax_20_affect = self.env['account.tax'].create({ 'name': "tax_20_affect", 'amount_type': 'percent', 'amount': 20.0, 'include_base_amount': True, }) tax_10 = self.env['account.tax'].create({ 'name': "tax_10", 'amount_type': 'percent', 'amount': 10.0, }) tax_5 = self.env['account.tax'].create({ 'name': "tax_5", 'amount_type': 'percent', 'amount': 5.0, }) invoice = self.env['account.move'].create({ 'move_type': 'out_invoice', 'partner_id': self.partner_a.id, 'invoice_date': '2019-01-01', 'invoice_line_ids': [ Command.create({ 'name': 'line1', 'account_id': self.company_data['default_account_revenue'].id, 'price_unit': 1000.0, 'tax_ids': [Command.set((tax_20_affect + tax_10 + tax_5).ids)], }), Command.create({ 'name': 'line2', 'account_id': self.company_data['default_account_revenue'].id, 'price_unit': 1000.0, 'tax_ids': [Command.set(tax_10.ids)], }), Command.create({ 'name': 'line3', 'account_id': self.company_data['default_account_revenue'].id, 'price_unit': 1000.0, 'tax_ids': [Command.set(tax_10.ids)], }), Command.create({ 'name': 'line4', 'account_id': self.company_data['default_account_revenue'].id, 'price_unit': 2000.0, 'tax_ids': [Command.set((tax_20_affect + tax_10).ids)], }), ] }) base_lines, tax_lines = self._dispatch_move_lines(invoice) tax_details = self._get_tax_details() self.assertTaxDetailsValues(tax_details, [ { 'base_line_id': base_lines[0].id, 'tax_line_id': tax_lines[2].id, 'base_amount': -200.0, 'tax_amount': -10.0, }, { 'base_line_id': base_lines[0].id, 'tax_line_id': tax_lines[1].id, 'base_amount': -200.0, 'tax_amount': -20.0, }, { 'base_line_id': base_lines[0].id, 'tax_line_id': tax_lines[2].id, 'base_amount': -1000.0, 'tax_amount': -50.0, }, { 'base_line_id': base_lines[0].id, 'tax_line_id': tax_lines[1].id, 'base_amount': -1000.0, 'tax_amount': -100.0, }, { 'base_line_id': base_lines[0].id, 'tax_line_id': tax_lines[0].id, 'base_amount': -1000.0, 'tax_amount': -200.0, }, { 'base_line_id': base_lines[1].id, 'tax_line_id': tax_lines[1].id, 'base_amount': -1000.0, 'tax_amount': -100.0, }, { 'base_line_id': base_lines[2].id, 'tax_line_id': tax_lines[1].id, 'base_amount': -1000.0, 'tax_amount': -100.0, }, { 'base_line_id': base_lines[3].id, 'tax_line_id': tax_lines[1].id, 'base_amount': -400.0, 'tax_amount': -40.0, }, { 'base_line_id': base_lines[3].id, 'tax_line_id': tax_lines[1].id, 'base_amount': -2000.0, 'tax_amount': -200.0, }, { 'base_line_id': base_lines[3].id, 'tax_line_id': tax_lines[3].id, 'base_amount': -2000.0, 'tax_amount': -400.0, }, ]) self.assertTotalAmounts(invoice, tax_details) # Same with a group of taxes tax_group = self.env['account.tax'].create({ 'name': "tax_group", 'amount_type': 'group', 'children_tax_ids': [Command.set((tax_20_affect + tax_10 + tax_5).ids)], }) invoice.write({ 'invoice_line_ids': [Command.update(base_lines[0].id, { 'tax_ids': [Command.set(tax_group.ids)], })], }) base_lines, tax_lines = self._dispatch_move_lines(invoice) tax_details = self._get_tax_details() self.assertTaxDetailsValues(tax_details, [ { 'base_line_id': base_lines[0].id, 'tax_line_id': tax_lines[4].id, 'base_amount': -200.0, 'tax_amount': -10.0, }, { 'base_line_id': base_lines[0].id, 'tax_line_id': tax_lines[3].id, 'base_amount': -200.0, 'tax_amount': -20.0, }, { 'base_line_id': base_lines[0].id, 'tax_line_id': tax_lines[4].id, 'base_amount': -1000.0, 'tax_amount': -50.0, }, { 'base_line_id': base_lines[0].id, 'tax_line_id': tax_lines[3].id, 'base_amount': -1000.0, 'tax_amount': -100.0, }, { 'base_line_id': base_lines[0].id, 'tax_line_id': tax_lines[2].id, 'base_amount': -1000.0, 'tax_amount': -200.0, }, { 'base_line_id': base_lines[1].id, 'tax_line_id': tax_lines[0].id, 'base_amount': -1000.0, 'tax_amount': -100.0, }, { 'base_line_id': base_lines[2].id, 'tax_line_id': tax_lines[0].id, 'base_amount': -1000.0, 'tax_amount': -100.0, }, { 'base_line_id': base_lines[3].id, 'tax_line_id': tax_lines[0].id, 'base_amount': -400.0, 'tax_amount': -40.0, }, { 'base_line_id': base_lines[3].id, 'tax_line_id': tax_lines[0].id, 'base_amount': -2000.0, 'tax_amount': -200.0, }, { 'base_line_id': base_lines[3].id, 'tax_line_id': tax_lines[1].id, 'base_amount': -2000.0, 'tax_amount': -400.0, }, ]) self.assertTotalAmounts(invoice, tax_details)
def test_zero_amount_tax(self): """ Ensure the tax details is generated for 0% tax. """ zero_tax = self.env['account.tax'].create({ 'name': "zero_tax", 'amount_type': 'percent', 'amount': 0.0, }) invoice = self.env['account.move'].create({ 'move_type': 'out_invoice', 'partner_id': self.partner_a.id, 'invoice_date': '2019-01-01', 'invoice_line_ids': [ Command.create({ 'name': 'line1', 'account_id': self.company_data['default_account_revenue'].id, 'price_unit': 1000.0, 'tax_ids': [Command.set(zero_tax.ids)], }), Command.create({ 'name': 'line2', 'account_id': self.company_data['default_account_revenue'].id, 'price_unit': 1000.0, 'tax_ids': [Command.set(zero_tax.ids)], }), ] }) base_lines, tax_lines = self._dispatch_move_lines(invoice) tax_details = self._get_tax_details() self.assertTaxDetailsValues( tax_details, [ { 'base_line_id': base_lines[0].id, 'tax_line_id': tax_lines[0].id, 'base_amount': -1000.0, 'tax_amount': 0.0, }, { 'base_line_id': base_lines[1].id, 'tax_line_id': tax_lines[0].id, 'base_amount': -1000.0, 'tax_amount': 0.0, }, ], ) self.assertTotalAmounts(invoice, tax_details) # Same with a group of taxes tax_group = self.env['account.tax'].create({ 'name': "tax_group", 'amount_type': 'group', 'children_tax_ids': [Command.set(zero_tax.ids)], }) invoice.write({ 'invoice_line_ids': [ Command.update(base_lines[0].id, {'tax_ids': [Command.set(tax_group.ids)]}), Command.update(base_lines[1].id, {'tax_ids': [Command.set(tax_group.ids)]}), ], }) base_lines, tax_lines = self._dispatch_move_lines(invoice) tax_details = self._get_tax_details() self.assertTaxDetailsValues( tax_details, [ { 'base_line_id': base_lines[0].id, 'tax_line_id': tax_lines[0].id, 'base_amount': -1000.0, 'tax_amount': 0.0, }, { 'base_line_id': base_lines[1].id, 'tax_line_id': tax_lines[0].id, 'base_amount': -1000.0, 'tax_amount': 0.0, }, ], ) self.assertTotalAmounts(invoice, tax_details)
def test_onchange_one2many_multi(self): """ test the effect of multiple onchange methods on one2many fields """ partner1 = self.env['res.partner'].create({'name': 'A partner'}) multi = self.env['test_new_api.multi'].create({'partner': partner1.id}) line1 = multi.lines.create({'multi': multi.id}) field_onchange = multi._onchange_spec() self.assertEqual( field_onchange, { 'name': '1', 'partner': '1', 'lines': None, 'lines.name': None, 'lines.partner': None, 'lines.tags': None, 'lines.tags.name': None, }) values = multi._convert_to_write( {key: multi[key] for key in ('name', 'partner', 'lines')}) self.assertEqual( values, { 'name': partner1.name, 'partner': partner1.id, 'lines': [Command.set([line1.id])], }) # modify 'partner' # -> set 'partner' on all lines # -> recompute 'name' # -> set 'name' on all lines partner2 = self.env['res.partner'].create({'name': 'A second partner'}) values = { 'name': partner1.name, 'partner': partner2.id, # this one just changed 'lines': [ Command.set([line1.id]), Command.create({ 'name': False, 'partner': False, 'tags': [Command.clear()] }) ], } self.env.cache.invalidate() result = multi.onchange(values, 'partner', field_onchange) self.assertEqual( result['value'], { 'name': partner2.name, 'lines': [ Command.clear(), Command.update( line1.id, { 'name': partner2.name, 'partner': (partner2.id, partner2.name), 'tags': [Command.clear()], }), Command.create({ 'name': partner2.name, 'partner': (partner2.id, partner2.name), 'tags': [Command.clear()], }), ], }) # do it again, but this time with a new tag on the second line values = { 'name': partner1.name, 'partner': partner2.id, # this one just changed 'lines': [ Command.set([line1.id]), Command.create({ 'name': False, 'partner': False, 'tags': [Command.clear(), Command.create({'name': 'Tag'})] }) ], } self.env.cache.invalidate() result = multi.onchange(values, 'partner', field_onchange) expected_value = { 'name': partner2.name, 'lines': [ Command.clear(), Command.update( line1.id, { 'name': partner2.name, 'partner': (partner2.id, partner2.name), 'tags': [Command.clear()], }), Command.create({ 'name': partner2.name, 'partner': (partner2.id, partner2.name), 'tags': [Command.clear(), Command.create({'name': 'Tag'})], }), ], } self.assertEqual(result['value'], expected_value) # ensure ID is not returned when asked and a many2many record is set to be created self.env.cache.invalidate() result = multi.onchange( values, 'partner', dict(field_onchange, **{'lines.tags.id': None})) self.assertEqual(result['value'], expected_value) # ensure inverse of one2many field is not returned self.env.cache.invalidate() result = multi.onchange(values, 'partner', dict(field_onchange, **{'lines.multi': None})) self.assertEqual(result['value'], expected_value)
def test_onchange_one2many(self): """ test the effect of onchange() on one2many fields """ USER = self.env.user # create an independent message message1 = self.Message.create({'body': "ABC"}) message2 = self.Message.create({'body': "ABC"}) self.assertEqual(message1.name, "[%s] %s" % ('', USER.name)) field_onchange = self.Discussion._onchange_spec() self.assertEqual(field_onchange.get('name'), '1') self.assertEqual(field_onchange.get('messages'), '1') self.assertItemsEqual( strip_prefix('messages.', field_onchange), ['author', 'body', 'name', 'size', 'important'], ) # modify discussion name values = { 'name': "Foo", 'categories': [], 'moderator': False, 'participants': [], 'messages': [ Command.link(message1.id), Command.link(message2.id), Command.update(message2.id, {'body': "XYZ"}), Command.create({ 'name': "[%s] %s" % ('', USER.name), 'body': "ABC", 'author': USER.id, 'size': 3, 'important': False, }), ], } self.env.cache.invalidate() result = self.Discussion.onchange(values, 'name', field_onchange) self.assertIn('messages', result['value']) self.assertEqual( result['value']['messages'], [ Command.clear(), Command.update( message1.id, { 'name': "[%s] %s" % ("Foo", USER.name), 'body': "ABC", 'author': USER.name_get()[0], 'size': 3, 'important': False, }), Command.update( message2.id, { 'name': "[%s] %s" % ("Foo", USER.name), 'body': "XYZ", # this must be sent back 'author': USER.name_get()[0], 'size': 3, 'important': False, }), Command.create({ 'name': "[%s] %s" % ("Foo", USER.name), 'body': "ABC", 'author': USER.name_get()[0], 'size': 3, 'important': False, }), ]) # ensure onchange changing one2many without subfield works one_level_fields = { k: v for k, v in field_onchange.items() if k.count('.') < 1 } values = dict(values, name='{generate_dummy_message}') result = self.Discussion.with_context( generate_dummy_message=True).onchange(values, 'name', one_level_fields) self.assertEqual(result['value']['messages'], [ Command.clear(), Command.link(message1.id), Command.link(message2.id), Command.create({}), Command.create({}), ])