diff options
| author | Ravi Singh <ras@odoo.com> | 2019-09-25 09:25:06 +0000 |
|---|---|---|
| committer | Xavier Morel <xmo@odoo.com> | 2020-02-21 12:12:19 +0000 |
| commit | 574d7f0d4ca18ae291ce0c0beeb51934bef0d41e (patch) | |
| tree | 095a5cf03dd2b421824a4d9fc54c7fe987a0d6b8 | |
| parent | 3ecea2c934063f93e3d9bcabc020ff090abf69b0 (diff) | |
[IMP] core: import-compatible export of m2m fields
When performing an import-compatible export, m2m values would be
exported as a record per cell unless the `id` subfield was the first
to be exported. Which is not the case when using the export UI (as it
always adds the field itself before any subfield). This would make the
m2m not actually export-compatible in most cases.
* export m2m "display name" in an import compatible format as well
* re-prioritise exporting xids when there are multiple m2m exports in
import-compatible mode
* never fall back on the o2m / non-import-compatible m2m path for m2ms
in import-compatible mode
Note: if multiple m2m fields are specified only one of them gets filled.
Task 2065428
closes odoo/odoo#37407
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Co-authored-by: Ravi Singh <ras@odoo.com>
Co-authored-by: Mohammed Shekha <msh@odoo.com>
Co-authored-by: Xavier Morel <xmo@odoo.com>
| -rw-r--r-- | odoo/addons/test_impex/tests/test_export.py | 18 | ||||
| -rw-r--r-- | odoo/models.py | 34 |
2 files changed, 41 insertions, 11 deletions
diff --git a/odoo/addons/test_impex/tests/test_export.py b/odoo/addons/test_impex/tests/test_export.py index 3d76ec925e6..01d322e0d15 100644 --- a/odoo/addons/test_impex/tests/test_export.py +++ b/odoo/addons/test_impex/tests/test_export.py @@ -606,18 +606,20 @@ class test_m2m(CreatorCase): def test_single_subfield(self): self.assertEqual( self.export([(0, False, {'value': 42})], - fields=['value', 'value/value']), + fields=['value', 'value/value'], + context={'import_compat': False}), [[u'export.many2many.other:42', 42]]) def test_integrate_one_in_parent(self): self.assertEqual( self.export([(0, False, {'value': 42})], - fields=['const', 'value/value']), + fields=['const', 'value/value'], + context={'import_compat': False}), [[4, 42]]) def test_multiple_records(self): self.assertEqual( - self.export(self.commands, fields=['const', 'value/value']), + self.export(self.commands, fields=['const', 'value/value'], context={'import_compat': False}), [ [4, 4], [u'', 42], @@ -630,6 +632,12 @@ class test_m2m(CreatorCase): self.assertEqual( self.export(self.commands, fields=['const', 'value']), [ + [4, 'export.many2many.other:4,export.many2many.other:42,export.many2many.other:36,export.many2many.other:4,export.many2many.other:13'], + ]) + + self.assertEqual( + self.export(self.commands, fields=['const', 'value'], context={'import_compat': False}), + [ [4, u'export.many2many.other:4'], ['', u'export.many2many.other:42'], ['', u'export.many2many.other:36'], @@ -664,6 +672,10 @@ class test_m2m(CreatorCase): r.with_context(import_compat=True)._export_rows([['value', 'id']]), [['__t__.record000,__t__.record001,__t__.record010,__t__.record011,__t__.record100']] ) + self.assertEqual( + r.with_context(import_compat=True)._export_rows([['value'], ['value', 'id']]), + [['', '__t__.record000,__t__.record001,__t__.record010,__t__.record011,__t__.record100']] + ) self.assertEqual( r.with_context(import_compat=False)._export_rows([['id'], ['value', 'id'], ['value', 'value']]), diff --git a/odoo/models.py b/odoo/models.py index f1c6b890935..33c966bb1be 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -22,6 +22,7 @@ """ import collections +import contextlib import datetime import dateutil import fnmatch @@ -838,18 +839,35 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): current[i] = field.convert_to_export(value, record) else: primary_done.append(name) - - # in import_compat mode, m2m should always be exported as - # a comma-separated list of xids in a single cell - if import_compatible and field.type == 'many2many' and len(path) > 1 and path[1] == 'id': - xml_ids = [xid for _, xid in value.__ensure_xml_id()] - current[i] = ','.join(xml_ids) or False - continue - # recursively export the fields that follow name; use # 'display_name' where no subfield is exported fields2 = [(p[1:] or ['display_name'] if p and p[0] == name else []) for p in fields] + + # in import_compat mode, m2m should always be exported as + # a comma-separated list of xids or names in a single cell + if import_compatible and field.type == 'many2many': + index = None + # find out which subfield the user wants & its + # location as we might not get it as the first + # column we encounter + for name in ['id', 'name', 'display_name']: + with contextlib.suppress(ValueError): + index = fields2.index([name]) + break + if index is None: + # not found anything, assume we just want the + # name_get in the first column + name = None + index = i + + if name == 'id': + xml_ids = [xid for _, xid in value.__ensure_xml_id()] + current[index] = ','.join(xml_ids) or False + else: + current[index] = field.convert_to_export(value, record) or False + continue + lines2 = value._export_rows(fields2, _is_toplevel_call=False) if lines2: # merge first line with record's main line |
