Odoo18-Base/addons/test_import_export/tests/test_properties.py

279 lines
11 KiB
Python
Raw Permalink Normal View History

2025-01-06 10:57:38 +07:00
from odoo.tests.common import RecordCapturer, TransactionCase
class TestPropertiesExportImport(TransactionCase):
maxDiff = None
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.ModelDefinition = cls.env['import.properties.definition']
cls.ModelProperty = cls.env['import.properties']
cls.definition_records = cls.ModelDefinition.create(
[
{
'properties_definition': [
{'name': 'char_prop', 'type': 'char', 'string': 'TextType', 'default': 'Def'},
{'name': 'separator_prop', 'type': 'separator', 'string': 'Separator'},
{
'name': 'selection_prop',
'type': 'selection',
'string': 'One Selection',
'selection': [
['selection_1', 'aaaaaaa'],
['selection_2', 'bbbbbbb'],
['selection_3', 'ccccccc'],
],
},
{
'name': 'm2o_prop',
'type': 'many2one',
'string': 'many2one',
'comodel': 'res.partner',
},
]
},
{
'properties_definition': [
{'name': 'bool_prop', 'type': 'boolean', 'string': 'CheckBox'},
{
'name': 'tags_prop',
'tags': [['aa', 'AA', 5], ['bb', 'BB', 6], ['cc', 'CC', 7]],
'type': 'tags',
'string': 'Tags',
},
{
'name': 'm2m_prop',
'type': 'many2many',
'string': 'M2M',
'comodel': 'res.partner',
},
]
},
]
)
cls.partners = cls.env['res.partner'].create(
[
{'name': 'Name Partner 1'},
{'name': 'Name Partner 2'},
{'name': 'Name Partner 3'},
]
)
cls.properties_records = cls.ModelProperty.create(
[
{
'record_definition_id': cls.definition_records[0].id,
'properties': {
'char_prop': 'Not the default',
'selection_prop': 'selection_2',
},
},
{
'record_definition_id': cls.definition_records[0].id,
'properties': {
'm2o_prop': cls.partners[0].id,
},
},
{
'record_definition_id': cls.definition_records[1].id,
'properties': {
'tags_prop': ['aa', 'bb'],
'bool_prop': True,
},
},
{
'record_definition_id': cls.definition_records[1].id,
'properties': {
'm2m_prop': cls.partners.ids,
},
},
]
)
def test_export_properties(self):
all_properties = [
[f"properties.{property_dict_type['name']}"]
for property_dict_type in self.definition_records[0].properties_definition
+ self.definition_records[1].properties_definition
if property_dict_type['type'] != 'separator'
]
# Without import compatibility
self.assertEqual(
self.properties_records.with_context(import_compat=False)._export_rows(all_properties),
[
['Not the default', 'bbbbbbb', '', '', '', ''],
['Def', '', 'Name Partner 1', '', '', ''],
['', '', '', True, 'AA,BB', ''],
['', '', '', '', '', 'Name Partner 1'],
['', '', '', '', '', 'Name Partner 2'],
['', '', '', '', '', 'Name Partner 3'],
],
)
# With import compatibility
self.assertEqual(
self.properties_records._export_rows(all_properties),
[
['Not the default', 'bbbbbbb', '', '', '', ''],
['Def', '', 'Name Partner 1', '', '', ''],
['', '', '', True, 'AA,BB', ''],
['', '', '', '', '', 'Name Partner 1,Name Partner 2,Name Partner 3'],
],
)
def test_import_properties(self):
def_record_1 = self.definition_records[0]
def_record_2 = self.definition_records[1]
values_list = [
[
"Record Definition Id",
# Field of the first definition
f"TextType ({def_record_1.display_name})", f"One Selection ({def_record_1.display_name})", f"many2one ({def_record_1.display_name})",
# Field of the second definition
f"CheckBox ({def_record_2.display_name})", "properties.tags_prop", f"M2M ({def_record_2.display_name})",
],
# Record attached to the first definition record
[
str(def_record_1.id),
'One Text', 'bbbbbbb', self.partners[0].display_name,
'', '', '',
], [
str(def_record_1.id),
'One Text', 'selection_3', self.partners[1].display_name,
'', '', '',
],
# Record attached to the second definition record
[
str(def_record_2.id),
'', '', '',
'True', 'aa', ','.join(self.partners[:2].mapped('display_name')),
], [
str(def_record_2.id),
'', '', '',
'0', 'BB', '',
],
]
import_wizard = self.env['base_import.import'].create({
'res_model': self.ModelProperty._name,
'file': '\n'.join([';'.join(values) for values in values_list]),
'file_type': 'text/csv',
})
opts = {'quoting': '"', 'separator': ';', 'has_headers': True}
preview = import_wizard.parse_preview(opts)
self.assertEqual(
preview['matches'],
{
0: ['record_definition_id'],
1: ['properties.char_prop'],
2: ['properties.selection_prop'],
3: ['properties.m2o_prop'],
4: ['properties.bool_prop'],
5: ['properties.tags_prop'],
6: ['properties.m2m_prop'],
},
)
with RecordCapturer(self.ModelProperty, []) as capture:
results = import_wizard.execute_import(
[fnames[0] for fnames in preview['matches'].values()],
[],
opts,
)
# if result is empty, no import error
self.assertItemsEqual(results['messages'], [])
records_created = capture.records
self.assertEqual(records_created.record_definition_id, def_record_1 + def_record_2)
self.assertEqual(records_created.mapped('properties'), [
{'char_prop': 'One Text', 'selection_prop': 'selection_2', 'm2o_prop': self.partners[0].id},
{'char_prop': 'One Text', 'selection_prop': 'selection_3', 'm2o_prop': self.partners[1].id},
{'bool_prop': True, 'tags_prop': ['aa'], 'm2m_prop': self.partners[:2].ids},
{'bool_prop': False, 'tags_prop': ['bb'], 'm2m_prop': False},
])
records_created._BaseModel__ensure_xml_id()
external_ids = [meta['xmlid'] for meta in records_created.get_metadata()]
# Test the update flow
values_list = [
[
"Id", "Record Definition Id",
# Field of the first definition
f"TextType ({def_record_1.display_name})", f"many2one ({def_record_1.display_name})",
# Field of the second definition
f"CheckBox ({def_record_2.display_name})", "properties.tags_prop", f"M2M ({def_record_2.display_name})",
],
# Record attached to the first definition record
[
external_ids[0], str(def_record_1.id),
'SSBIYXRlIHRoaXMgZmVhdHVyZQ==', str(self.partners[2].id),
'', '', '',
],
# Record attached to the second definition record
[
external_ids[1], str(def_record_2.id), # record that changed its parent
'', '',
'FaLse', 'AA', f'{self.partners[1].id}',
],
[
external_ids[2], str(def_record_2.id),
'', '',
'false', 'bb,CC', '',
],
[
external_ids[3], str(def_record_2.id),
'', '',
'1', 'BB', f'{self.partners[1].id},{self.partners[2].id}',
],
]
import_wizard = self.env['base_import.import'].create({
'res_model': self.ModelProperty._name,
'file': '\n'.join([';'.join(values) for values in values_list]),
'file_type': 'text/csv',
})
opts = {'quoting': '"', 'separator': ';', 'has_headers': True}
preview = import_wizard.parse_preview(opts)
self.assertEqual(
preview['matches'],
{
0: ['id'],
1: ['record_definition_id'],
2: ['properties.char_prop'],
3: ['properties.m2o_prop'],
4: ['properties.bool_prop'],
5: ['properties.tags_prop'],
6: ['properties.m2m_prop'],
},
)
results = import_wizard.execute_import(
[
'id',
'record_definition_id',
'properties.char_prop',
'properties.m2o_prop/.id',
'properties.bool_prop',
'properties.tags_prop',
'properties.m2m_prop/.id',
],
[],
opts,
)
self.assertItemsEqual(results['messages'], [])
self.assertEqual(records_created.mapped('properties'), [
{'char_prop': 'SSBIYXRlIHRoaXMgZmVhdHVyZQ==', 'selection_prop': 'selection_2', 'm2o_prop': self.partners[2].id},
{'bool_prop': False, 'tags_prop': ['aa'], 'm2m_prop': self.partners[1].ids},
{'bool_prop': False, 'tags_prop': ['bb', 'cc'], 'm2m_prop': False},
{'bool_prop': True, 'tags_prop': ['bb'], 'm2m_prop': self.partners[1:].ids},
])