524 lines
23 KiB
Python
524 lines
23 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||
|
|
||
|
from psycopg2 import IntegrityError
|
||
|
|
||
|
from odoo.exceptions import ValidationError
|
||
|
from odoo.tests.common import Form, TransactionCase, HttpCase, tagged
|
||
|
from odoo.tools import mute_logger
|
||
|
from odoo import Command
|
||
|
|
||
|
|
||
|
class TestXMLID(TransactionCase):
|
||
|
def get_data(self, xml_id):
|
||
|
""" Return the 'ir.model.data' record corresponding to ``xml_id``. """
|
||
|
module, suffix = xml_id.split('.', 1)
|
||
|
domain = [('module', '=', module), ('name', '=', suffix)]
|
||
|
return self.env['ir.model.data'].search(domain)
|
||
|
|
||
|
def test_create(self):
|
||
|
model = self.env['res.partner.category']
|
||
|
xml_id = 'test_convert.category_foo'
|
||
|
|
||
|
# create category (flag 'noupdate' should be False by default)
|
||
|
data = dict(xml_id=xml_id, values={'name': 'Foo'})
|
||
|
category = model._load_records([data])
|
||
|
self.assertEqual(category, self.env.ref(xml_id, raise_if_not_found=False))
|
||
|
self.assertEqual(category.name, 'Foo')
|
||
|
self.assertEqual(self.get_data(xml_id).noupdate, False)
|
||
|
|
||
|
# update category
|
||
|
data = dict(xml_id=xml_id, values={'name': 'Bar'})
|
||
|
category1 = model._load_records([data], update=True)
|
||
|
self.assertEqual(category, category1)
|
||
|
self.assertEqual(category.name, 'Bar')
|
||
|
self.assertEqual(self.get_data(xml_id).noupdate, False)
|
||
|
|
||
|
# update category
|
||
|
data = dict(xml_id=xml_id, values={'name': 'Baz'}, noupdate=True)
|
||
|
category2 = model._load_records([data], update=True)
|
||
|
self.assertEqual(category, category2)
|
||
|
self.assertEqual(category.name, 'Baz')
|
||
|
self.assertEqual(self.get_data(xml_id).noupdate, False)
|
||
|
|
||
|
def test_create_noupdate(self):
|
||
|
model = self.env['res.partner.category']
|
||
|
xml_id = 'test_convert.category_foo'
|
||
|
|
||
|
# create category
|
||
|
data = dict(xml_id=xml_id, values={'name': 'Foo'}, noupdate=True)
|
||
|
category = model._load_records([data])
|
||
|
self.assertEqual(category, self.env.ref(xml_id, raise_if_not_found=False))
|
||
|
self.assertEqual(category.name, 'Foo')
|
||
|
self.assertEqual(self.get_data(xml_id).noupdate, True)
|
||
|
|
||
|
# update category
|
||
|
data = dict(xml_id=xml_id, values={'name': 'Bar'}, noupdate=False)
|
||
|
category1 = model._load_records([data], update=True)
|
||
|
self.assertEqual(category, category1)
|
||
|
self.assertEqual(category.name, 'Foo')
|
||
|
self.assertEqual(self.get_data(xml_id).noupdate, True)
|
||
|
|
||
|
# update category
|
||
|
data = dict(xml_id=xml_id, values={'name': 'Baz'}, noupdate=True)
|
||
|
category2 = model._load_records([data], update=True)
|
||
|
self.assertEqual(category, category2)
|
||
|
self.assertEqual(category.name, 'Foo')
|
||
|
self.assertEqual(self.get_data(xml_id).noupdate, True)
|
||
|
|
||
|
def test_create_noupdate_multi(self):
|
||
|
model = self.env['res.partner.category']
|
||
|
data_list = [
|
||
|
dict(xml_id='test_convert.category_foo', values={'name': 'Foo'}, noupdate=True),
|
||
|
dict(xml_id='test_convert.category_bar', values={'name': 'Bar'}, noupdate=True),
|
||
|
]
|
||
|
|
||
|
# create category
|
||
|
categories = model._load_records(data_list)
|
||
|
foo = self.env.ref('test_convert.category_foo')
|
||
|
bar = self.env.ref('test_convert.category_bar')
|
||
|
self.assertEqual(categories, foo + bar)
|
||
|
self.assertEqual(foo.name, 'Foo')
|
||
|
self.assertEqual(bar.name, 'Bar')
|
||
|
|
||
|
# check data
|
||
|
self.assertEqual(self.get_data('test_convert.category_foo').noupdate, True)
|
||
|
self.assertEqual(self.get_data('test_convert.category_bar').noupdate, True)
|
||
|
|
||
|
def test_create_order(self):
|
||
|
model = self.env['res.partner.category']
|
||
|
data_list = [
|
||
|
dict(xml_id='test_convert.category_foo', values={'name': 'Foo'}),
|
||
|
dict(xml_id='test_convert.category_bar', values={'name': 'Bar'}, noupdate=True),
|
||
|
dict(xml_id='test_convert.category_baz', values={'name': 'Baz'}),
|
||
|
]
|
||
|
|
||
|
# create categories
|
||
|
foo = model._load_records([data_list[0]])
|
||
|
bar = model._load_records([data_list[1]])
|
||
|
baz = model._load_records([data_list[2]])
|
||
|
self.assertEqual(foo.name, 'Foo')
|
||
|
self.assertEqual(bar.name, 'Bar')
|
||
|
self.assertEqual(baz.name, 'Baz')
|
||
|
|
||
|
# update them, and check the order of result
|
||
|
for data in data_list:
|
||
|
data['values']['name'] += 'X'
|
||
|
cats = model._load_records(data_list, update=True)
|
||
|
self.assertEqual(list(cats), [foo, bar, baz])
|
||
|
self.assertEqual(foo.name, 'FooX')
|
||
|
self.assertEqual(bar.name, 'Bar')
|
||
|
self.assertEqual(baz.name, 'BazX')
|
||
|
|
||
|
def test_create_inherits(self):
|
||
|
model = self.env['res.users']
|
||
|
xml_id = 'test_convert.user_foo'
|
||
|
par_xml_id = xml_id + '_res_partner'
|
||
|
|
||
|
# create user
|
||
|
user = model._load_records([dict(xml_id=xml_id, values={'name': 'Foo', 'login': 'foo'})])
|
||
|
self.assertEqual(user, self.env.ref(xml_id, raise_if_not_found=False))
|
||
|
self.assertEqual(user.partner_id, self.env.ref(par_xml_id, raise_if_not_found=False))
|
||
|
self.assertEqual(user.name, 'Foo')
|
||
|
self.assertEqual(user.login, 'foo')
|
||
|
|
||
|
def test_recreate(self):
|
||
|
model = self.env['res.partner.category']
|
||
|
xml_id = 'test_convert.category_foo'
|
||
|
data = dict(xml_id=xml_id, values={'name': 'Foo'})
|
||
|
|
||
|
# create category
|
||
|
category = model._load_records([data])
|
||
|
self.assertEqual(category, self.env.ref(xml_id, raise_if_not_found=False))
|
||
|
self.assertEqual(category.name, 'Foo')
|
||
|
|
||
|
# suppress category
|
||
|
category.unlink()
|
||
|
self.assertFalse(self.env.ref(xml_id, raise_if_not_found=False))
|
||
|
|
||
|
# update category, this should recreate it
|
||
|
category = model._load_records([data], update=True)
|
||
|
self.assertEqual(category, self.env.ref(xml_id, raise_if_not_found=False))
|
||
|
self.assertEqual(category.name, 'Foo')
|
||
|
|
||
|
def test_create_xmlids(self):
|
||
|
# create users and assign them xml ids
|
||
|
foo, bar = self.env['res.users']._load_records([{
|
||
|
'xml_id': 'test_convert.foo',
|
||
|
'values': {'name': 'Foo', 'login': 'foo'},
|
||
|
'noupdate': True,
|
||
|
}, {
|
||
|
'xml_id': 'test_convert.bar',
|
||
|
'values': {'name': 'Bar', 'login': 'bar'},
|
||
|
'noupdate': True,
|
||
|
}])
|
||
|
|
||
|
self.assertEqual(foo, self.env.ref('test_convert.foo', raise_if_not_found=False))
|
||
|
self.assertEqual(bar, self.env.ref('test_convert.bar', raise_if_not_found=False))
|
||
|
|
||
|
self.assertEqual(foo.partner_id, self.env.ref('test_convert.foo_res_partner', raise_if_not_found=False))
|
||
|
self.assertEqual(bar.partner_id, self.env.ref('test_convert.bar_res_partner', raise_if_not_found=False))
|
||
|
|
||
|
self.assertEqual(self.get_data('test_convert.foo').noupdate, True)
|
||
|
self.assertEqual(self.get_data('test_convert.bar').noupdate, True)
|
||
|
|
||
|
@mute_logger('odoo.sql_db', 'odoo.addons.base.models.ir_model')
|
||
|
def test_create_external_id_with_space(self):
|
||
|
model = self.env['res.partner.category']
|
||
|
data_list = [{
|
||
|
'xml_id': 'test_convert.category_with space',
|
||
|
'values': {'name': 'Bar'},
|
||
|
}]
|
||
|
with self.assertRaisesRegex(IntegrityError, 'ir_model_data_name_nospaces'):
|
||
|
model._load_records(data_list)
|
||
|
|
||
|
def test_update_xmlid(self):
|
||
|
def assert_xmlid(xmlid, value, message):
|
||
|
expected_values = (value._name, value.id)
|
||
|
with self.assertQueryCount(0):
|
||
|
self.assertEqual(self.env['ir.model.data']._xmlid_lookup(xmlid), expected_values, message)
|
||
|
module, name = xmlid.split('.')
|
||
|
self.env.cr.execute("SELECT model, res_id FROM ir_model_data where module=%s and name=%s", [module, name])
|
||
|
self.assertEqual((value._name, value.id), self.env.cr.fetchone(), message)
|
||
|
|
||
|
xmlid = 'base.test_xmlid'
|
||
|
records = self.env['ir.model.data'].search([], limit=6)
|
||
|
with self.assertQueryCount(1):
|
||
|
self.env['ir.model.data']._update_xmlids([
|
||
|
{'xml_id': xmlid, 'record': records[0]},
|
||
|
])
|
||
|
assert_xmlid(xmlid, records[0], f'The xmlid {xmlid} should have been created with record {records[0]}')
|
||
|
|
||
|
with self.assertQueryCount(1):
|
||
|
self.env['ir.model.data']._update_xmlids([
|
||
|
{'xml_id': xmlid, 'record': records[1]},
|
||
|
], update=True)
|
||
|
assert_xmlid(xmlid, records[1], f'The xmlid {xmlid} should have been updated with record {records[1]}')
|
||
|
|
||
|
with self.assertQueryCount(1):
|
||
|
self.env['ir.model.data']._update_xmlids([
|
||
|
{'xml_id': xmlid, 'record': records[2]},
|
||
|
])
|
||
|
assert_xmlid(xmlid, records[2], f'The xmlid {xmlid} should have been updated with record {records[1]}')
|
||
|
|
||
|
# noupdate case
|
||
|
# note: this part is mainly there to avoid breaking the current behaviour, not asserting that it makes sence
|
||
|
xmlid = 'base.test_xmlid_noupdates'
|
||
|
with self.assertQueryCount(1):
|
||
|
self.env['ir.model.data']._update_xmlids([
|
||
|
{'xml_id': xmlid, 'record': records[3], 'noupdate':True}, # record created as noupdate
|
||
|
])
|
||
|
|
||
|
assert_xmlid(xmlid, records[3], f'The xmlid {xmlid} should have been created for record {records[2]}')
|
||
|
|
||
|
with self.assertQueryCount(1):
|
||
|
self.env['ir.model.data']._update_xmlids([
|
||
|
{'xml_id': xmlid, 'record': records[4]},
|
||
|
], update=True)
|
||
|
assert_xmlid(xmlid, records[3], f'The xmlid {xmlid} should not have been updated (update mode)')
|
||
|
|
||
|
with self.assertQueryCount(1):
|
||
|
self.env['ir.model.data']._update_xmlids([
|
||
|
{'xml_id': xmlid, 'record': records[5]},
|
||
|
])
|
||
|
assert_xmlid(xmlid, records[5], f'The xmlid {xmlid} should have been updated with record (not an update) {records[1]}')
|
||
|
|
||
|
class TestIrModel(TransactionCase):
|
||
|
|
||
|
@classmethod
|
||
|
def setUpClass(cls):
|
||
|
super().setUpClass()
|
||
|
|
||
|
# The test mode is necessary in this case. After each test, we call
|
||
|
# registry.reset_changes(), which opens a new cursor to retrieve custom
|
||
|
# models and fields. A regular cursor would correspond to the state of
|
||
|
# the database before setUpClass(), which is not correct. Instead, a
|
||
|
# test cursor will correspond to the state of the database of cls.cr at
|
||
|
# that point, i.e., before the call to setUp().
|
||
|
cls.registry.enter_test_mode(cls.cr)
|
||
|
cls.addClassCleanup(cls.registry.leave_test_mode)
|
||
|
|
||
|
# model and records for banana stages
|
||
|
cls.env['ir.model'].create({
|
||
|
'name': 'Banana Ripeness',
|
||
|
'model': 'x_banana_ripeness',
|
||
|
'field_id': [
|
||
|
Command.create({'name': 'x_name', 'ttype': 'char', 'field_description': 'Name'}),
|
||
|
]
|
||
|
})
|
||
|
# stage values are pairs (id, display_name)
|
||
|
cls.ripeness_green = cls.env['x_banana_ripeness'].name_create('Green')
|
||
|
cls.ripeness_okay = cls.env['x_banana_ripeness'].name_create('Okay, I guess?')
|
||
|
cls.ripeness_gone = cls.env['x_banana_ripeness'].name_create('Walked away on its own')
|
||
|
|
||
|
# model and records for bananas
|
||
|
cls.bananas_model = cls.env['ir.model'].create({
|
||
|
'name': 'Bananas',
|
||
|
'model': 'x_bananas',
|
||
|
'field_id': [
|
||
|
Command.create({'name': 'x_name', 'ttype': 'char', 'field_description': 'Name'}),
|
||
|
Command.create({'name': 'x_length', 'ttype': 'float', 'field_description': 'Length'}),
|
||
|
Command.create({'name': 'x_color', 'ttype': 'integer', 'field_description': 'Color'}),
|
||
|
Command.create({'name': 'x_ripeness_id', 'ttype': 'many2one',
|
||
|
'field_description': 'Ripeness','relation': 'x_banana_ripeness',
|
||
|
'group_expand': True})
|
||
|
]
|
||
|
})
|
||
|
# add non-stored field that is not valid in order
|
||
|
cls.env['ir.model.fields'].create({
|
||
|
'name': 'x_is_yellow',
|
||
|
'field_description': 'Is the banana yellow?',
|
||
|
'ttype': 'boolean',
|
||
|
'model_id': cls.bananas_model.id,
|
||
|
'store': False,
|
||
|
'depends': 'x_color',
|
||
|
'compute': "for banana in self:\n banana['x_is_yellow'] = banana.x_color == 9"
|
||
|
})
|
||
|
# default stage is ripeness_green
|
||
|
cls.env['ir.default'].set('x_bananas', 'x_ripeness_id', cls.ripeness_green[0])
|
||
|
cls.env['x_bananas'].create([{
|
||
|
'x_name': 'Banana #1',
|
||
|
'x_length': 3.14159,
|
||
|
'x_color': 9,
|
||
|
}, {
|
||
|
'x_name': 'Banana #2',
|
||
|
'x_length': 0,
|
||
|
'x_color': 6,
|
||
|
}, {
|
||
|
'x_name': 'Banana #3',
|
||
|
'x_length': 10,
|
||
|
'x_color': 6,
|
||
|
}])
|
||
|
|
||
|
def setUp(self):
|
||
|
# this cleanup is necessary after each test, and must be done last
|
||
|
self.addCleanup(self.registry.reset_changes)
|
||
|
super().setUp()
|
||
|
|
||
|
def test_model_order_constraint(self):
|
||
|
"""Check that the order constraint is properly enforced."""
|
||
|
VALID_ORDERS = ['id', 'id desc', 'id asc, x_length', 'x_color, x_length, create_uid']
|
||
|
for order in VALID_ORDERS:
|
||
|
self.bananas_model.order = order
|
||
|
|
||
|
INVALID_ORDERS = ['', 'x_wat', 'id esc', 'create_uid,', 'id, x_is_yellow']
|
||
|
for order in INVALID_ORDERS:
|
||
|
with self.assertRaises(ValidationError), self.cr.savepoint():
|
||
|
self.bananas_model.order = order
|
||
|
|
||
|
# check that the constraint is checked at model creation
|
||
|
fields_value = [
|
||
|
Command.create({'name': 'x_name', 'ttype': 'char', 'field_description': 'Name'}),
|
||
|
Command.create({'name': 'x_length', 'ttype': 'float', 'field_description': 'Length'}),
|
||
|
Command.create({'name': 'x_color', 'ttype': 'integer', 'field_description': 'Color'}),
|
||
|
]
|
||
|
self.env['ir.model'].create({
|
||
|
'name': 'MegaBananas',
|
||
|
'model': 'x_mega_bananas',
|
||
|
'order': 'x_name asc, id desc', # valid order
|
||
|
'field_id': fields_value,
|
||
|
})
|
||
|
with self.assertRaises(ValidationError):
|
||
|
self.env['ir.model'].create({
|
||
|
'name': 'GigaBananas',
|
||
|
'model': 'x_giga_bananas',
|
||
|
'order': 'x_name asc, x_wat', # invalid order
|
||
|
'field_id': fields_value,
|
||
|
})
|
||
|
|
||
|
def test_model_order_search(self):
|
||
|
"""Check that custom orders are applied when querying a model."""
|
||
|
ORDERS = {
|
||
|
'id asc': ['Banana #1', 'Banana #2', 'Banana #3'],
|
||
|
'id desc': ['Banana #3', 'Banana #2', 'Banana #1'],
|
||
|
'x_color asc, id asc': ['Banana #2', 'Banana #3', 'Banana #1'],
|
||
|
'x_color asc, id desc': ['Banana #3', 'Banana #2', 'Banana #1'],
|
||
|
'x_length asc, id': ['Banana #2', 'Banana #1', 'Banana #3'],
|
||
|
}
|
||
|
for order, names in ORDERS.items():
|
||
|
self.bananas_model.order = order
|
||
|
self.assertEqual(self.env['x_bananas']._order, order)
|
||
|
|
||
|
bananas = self.env['x_bananas'].search([])
|
||
|
self.assertEqual(bananas.mapped('x_name'), names, 'failed to order by %s' % order)
|
||
|
|
||
|
def test_group_expansion(self):
|
||
|
"""Check that the basic custom group expansion works."""
|
||
|
groups = self.env['x_bananas'].read_group(domain=[],
|
||
|
fields=['x_ripeness_id'],
|
||
|
groupby=['x_ripeness_id'])
|
||
|
expected = [{
|
||
|
'x_ripeness_id': self.ripeness_green,
|
||
|
'x_ripeness_id_count': 3,
|
||
|
'__domain': [('x_ripeness_id', '=', self.ripeness_green[0])],
|
||
|
}, {
|
||
|
'x_ripeness_id': self.ripeness_okay,
|
||
|
'x_ripeness_id_count': 0,
|
||
|
'__domain': [('x_ripeness_id', '=', self.ripeness_okay[0])],
|
||
|
}, {
|
||
|
'x_ripeness_id': self.ripeness_gone,
|
||
|
'x_ripeness_id_count': 0,
|
||
|
'__domain': [('x_ripeness_id', '=', self.ripeness_gone[0])],
|
||
|
}]
|
||
|
self.assertEqual(groups, expected, 'should include 2 empty ripeness stages')
|
||
|
|
||
|
def test_rec_name_deletion(self):
|
||
|
"""Check that deleting 'x_name' does not crash."""
|
||
|
record = self.env['x_bananas'].create({'x_name': "Ifan Ben-Mezd"})
|
||
|
self.assertEqual(record._rec_name, 'x_name')
|
||
|
self.assertEqual(self.registry.field_depends[type(record).display_name], ('x_name',))
|
||
|
self.assertEqual(record.display_name, "Ifan Ben-Mezd")
|
||
|
|
||
|
# unlinking x_name should fixup _rec_name and display_name
|
||
|
self.env['ir.model.fields']._get('x_bananas', 'x_name').unlink()
|
||
|
record = self.env['x_bananas'].browse(record.id)
|
||
|
self.assertEqual(record._rec_name, None)
|
||
|
self.assertEqual(self.registry.field_depends[type(record).display_name], ())
|
||
|
self.assertEqual(record.display_name, f"x_bananas,{record.id}")
|
||
|
|
||
|
def test_monetary_currency_field(self):
|
||
|
fields_value = [
|
||
|
Command.create({'name': 'x_monetary', 'ttype': 'monetary', 'field_description': 'Monetary', 'currency_field': 'test'}),
|
||
|
]
|
||
|
with self.assertRaises(ValidationError):
|
||
|
self.env['ir.model'].create({
|
||
|
'name': 'Paper Company Model',
|
||
|
'model': 'x_paper_model',
|
||
|
'field_id': fields_value,
|
||
|
})
|
||
|
|
||
|
fields_value = [
|
||
|
Command.create({'name': 'x_monetary', 'ttype': 'monetary', 'field_description': 'Monetary', 'currency_field': 'x_falsy_currency'}),
|
||
|
Command.create({'name': 'x_falsy_currency', 'ttype': 'one2many', 'field_description': 'Currency', 'relation': 'res.currency'}),
|
||
|
]
|
||
|
with self.assertRaises(ValidationError):
|
||
|
self.env['ir.model'].create({
|
||
|
'name': 'Paper Company Model',
|
||
|
'model': 'x_paper_model',
|
||
|
'field_id': fields_value,
|
||
|
})
|
||
|
|
||
|
fields_value = [
|
||
|
Command.create({'name': 'x_monetary', 'ttype': 'monetary', 'field_description': 'Monetary', 'currency_field': 'x_falsy_currency'}),
|
||
|
Command.create({'name': 'x_falsy_currency', 'ttype': 'many2one', 'field_description': 'Currency', 'relation': 'res.partner'}),
|
||
|
]
|
||
|
with self.assertRaises(ValidationError):
|
||
|
self.env['ir.model'].create({
|
||
|
'name': 'Paper Company Model',
|
||
|
'model': 'x_paper_model',
|
||
|
'field_id': fields_value,
|
||
|
})
|
||
|
|
||
|
fields_value = [
|
||
|
Command.create({'name': 'x_monetary', 'ttype': 'monetary', 'field_description': 'Monetary', 'currency_field': 'x_good_currency'}),
|
||
|
Command.create({'name': 'x_good_currency', 'ttype': 'many2one', 'field_description': 'Currency', 'relation': 'res.currency'}),
|
||
|
]
|
||
|
model = self.env['ir.model'].create({
|
||
|
'name': 'Paper Company Model',
|
||
|
'model': 'x_paper_model',
|
||
|
'field_id': fields_value,
|
||
|
})
|
||
|
monetary_field = model.field_id.search([['name', 'ilike', 'x_monetary']])
|
||
|
self.assertEqual(len(monetary_field), 1,
|
||
|
"Should have the monetary field in the created ir.model")
|
||
|
self.assertEqual(monetary_field.currency_field, "x_good_currency",
|
||
|
"The currency field in monetary should have x_good_currency as name")
|
||
|
|
||
|
@tagged('-at_install', 'post_install')
|
||
|
class TestIrModelEdition(TransactionCase):
|
||
|
def test_new_ir_model_fields_related(self):
|
||
|
"""Check that related field are handled correctly on new field"""
|
||
|
model = self.env['ir.model'].create({
|
||
|
'name': 'Bananas',
|
||
|
'model': 'x_bananas'
|
||
|
})
|
||
|
with self.debug_mode():
|
||
|
form = Form(self.env['ir.model.fields'].with_context(default_model_id=model.id))
|
||
|
form.related = 'id'
|
||
|
self.assertEqual(form.ttype, 'integer')
|
||
|
|
||
|
def test_delete_manual_models_with_base_fields(self):
|
||
|
model = self.env["ir.model"].create({
|
||
|
"model": "x_test_base_delete",
|
||
|
"name": "test base delete",
|
||
|
"field_id": [
|
||
|
Command.create({
|
||
|
"name": "x_my_field",
|
||
|
"ttype": "char",
|
||
|
}),
|
||
|
Command.create({
|
||
|
"name": "active",
|
||
|
"ttype": "boolean",
|
||
|
"state": "base",
|
||
|
})
|
||
|
]
|
||
|
})
|
||
|
model2 = self.env["ir.model"].create({
|
||
|
"model": "x_test_base_delete2",
|
||
|
"name": "test base delete2",
|
||
|
"field_id": [
|
||
|
Command.create({
|
||
|
"name": "x_my_field2",
|
||
|
"ttype": "char",
|
||
|
}),
|
||
|
Command.create({
|
||
|
"name": "active",
|
||
|
"ttype": "boolean",
|
||
|
"state": "base",
|
||
|
})
|
||
|
]
|
||
|
})
|
||
|
self.assertTrue(model.exists())
|
||
|
self.assertTrue(model2.exists())
|
||
|
|
||
|
self.env["ir.model"].browse(model.ids + model2.ids).unlink()
|
||
|
self.assertFalse(model.exists())
|
||
|
self.assertFalse(model2.exists())
|
||
|
|
||
|
@tagged('test_eval_context')
|
||
|
class TestEvalContext(TransactionCase):
|
||
|
|
||
|
def test_module_usage(self):
|
||
|
self.env['ir.model.fields'].create({
|
||
|
'name': 'x_foo_bar_baz',
|
||
|
'model_id': self.env['ir.model'].search([('model', '=', 'res.partner')]).id,
|
||
|
'field_description': 'foo',
|
||
|
'ttype': 'integer',
|
||
|
'store': False,
|
||
|
'depends': 'name',
|
||
|
'compute': ("time.time()\ndatetime.datetime.now()\n"
|
||
|
"dateutil.relativedelta.relativedelta(hours=1)")
|
||
|
})
|
||
|
self.env['res.partner'].create({'name': 'foo'}).x_foo_bar_baz
|
||
|
|
||
|
@tagged('-at_install', 'post_install')
|
||
|
class TestIrModelFieldsTranslation(HttpCase):
|
||
|
def test_ir_model_fields_translation(self):
|
||
|
# If not enabled (like in demo data), landing on res.config will try
|
||
|
# to disable module_sale_quotation_builder and raise an warning
|
||
|
group_order_template = self.env.ref('sale_management.group_sale_order_template', raise_if_not_found=False)
|
||
|
if group_order_template:
|
||
|
self.env.ref('base.group_user').write({"implied_ids": [(4, group_order_template.id)]})
|
||
|
|
||
|
# modify en_US translation
|
||
|
field = self.env['ir.model.fields'].search([('model_id.model', '=', 'res.users'), ('name', '=', 'login')])
|
||
|
self.assertEqual(field.with_context(lang='en_US').field_description, 'Login')
|
||
|
# check the name column of res.users is displayed as 'Login'
|
||
|
self.start_tour("/web", 'ir_model_fields_translation_en_tour', login="admin")
|
||
|
field.update_field_translations('field_description', {'en_US': 'Login2'})
|
||
|
# check the name column of res.users is displayed as 'Login2'
|
||
|
self.start_tour("/web", 'ir_model_fields_translation_en_tour2', login="admin")
|
||
|
|
||
|
# modify fr_FR translation
|
||
|
self.env['res.lang']._activate_lang('fr_FR')
|
||
|
field = self.env['ir.model.fields'].search([('model_id.model', '=', 'res.users'), ('name', '=', 'login')])
|
||
|
field.update_field_translations('field_description', {'fr_FR': 'Identifiant'})
|
||
|
self.assertEqual(field.with_context(lang='fr_FR').field_description, 'Identifiant')
|
||
|
admin = self.env['res.users'].search([('login', '=', 'admin')], limit=1)
|
||
|
admin.lang = 'fr_FR'
|
||
|
# check the name column of res.users is displayed as 'Identifiant'
|
||
|
self.start_tour("/web", 'ir_model_fields_translation_fr_tour', login="admin")
|
||
|
field.update_field_translations('field_description', {'fr_FR': 'Identifiant2'})
|
||
|
# check the name column of res.users is displayed as 'Identifiant2'
|
||
|
self.start_tour("/web", 'ir_model_fields_translation_fr_tour2', login="admin")
|