Import preview failed due to: .
diff --git a/addons/base_import/tests/test_base_import.py b/addons/base_import/tests/test_base_import.py
index 4b5224f0db0..2a70080fe5d 100644
--- a/addons/base_import/tests/test_base_import.py
+++ b/addons/base_import/tests/test_base_import.py
@@ -357,7 +357,7 @@ class TestPreview(TransactionCase):
{'id': 'somevalue', 'name': 'somevalue', 'string': 'Some Value', 'required': True, 'fields': [], 'type': 'integer', 'model_name': 'base_import.tests.models.preview'},
{'id': 'othervalue', 'name': 'othervalue', 'string': 'Other Variable', 'required': False, 'fields': [], 'type': 'integer', 'model_name': 'base_import.tests.models.preview'},
])
- self.assertEqual(result['preview'], ['foo', '5', '4'])
+ self.assertEqual(result['preview'], [['foo', 'bar', 'qux'], ['5'], ['4', '6']])
@unittest.skipUnless(can_import('xlrd'), "XLRD module not available")
def test_xls_success(self):
@@ -381,7 +381,7 @@ class TestPreview(TransactionCase):
{'id': 'somevalue', 'name': 'somevalue', 'string': 'Some Value', 'required': True, 'fields': [], 'type': 'integer', 'model_name': 'base_import.tests.models.preview'},
{'id': 'othervalue', 'name': 'othervalue', 'string': 'Other Variable', 'required': False, 'fields': [], 'type': 'integer', 'model_name': 'base_import.tests.models.preview'},
])
- self.assertEqual(result['preview'], ['foo', '1', '2'])
+ self.assertEqual(result['preview'], [['foo', 'bar', 'qux'], ['1', '3', '5'], ['2', '4', '6']])
@unittest.skipUnless(can_import('xlrd.xlsx'), "XLRD/XLSX not available")
def test_xlsx_success(self):
@@ -405,7 +405,7 @@ class TestPreview(TransactionCase):
{'id': 'somevalue', 'name': 'somevalue', 'string': 'Some Value', 'required': True, 'fields': [], 'type': 'integer', 'model_name': 'base_import.tests.models.preview'},
{'id': 'othervalue', 'name': 'othervalue', 'string': 'Other Variable', 'required': False, 'fields': [], 'type': 'integer', 'model_name': 'base_import.tests.models.preview'},
])
- self.assertEqual(result['preview'], ['foo', '1', '2'])
+ self.assertEqual(result['preview'], [['foo', 'bar', 'qux'], ['1', '3', '5'], ['2', '4', '6']])
@unittest.skipUnless(can_import('odf'), "ODFPY not available")
def test_ods_success(self):
@@ -648,6 +648,65 @@ class test_convert_import_data(TransactionCase):
self.assertItemsEqual(data, [data_row])
+ def test_set_empty_value_import(self):
+ partners_before = self.env['res.partner'].search([])
+ import_wizard = self.env['base_import.import'].create({
+ 'res_model': 'res.partner',
+ 'file': """foo,US,person\n
+foo1,Invalid Country,person\n
+foo2,US,persons\n""",
+ 'file_type': 'text/csv'
+ })
+
+ results = import_wizard.execute_import(
+ ['name', 'country_id', 'company_type'],
+ [],
+ {
+ 'quoting': '"',
+ 'separator': ',',
+ 'import_set_empty_fields': ['country_id', 'company_type'],
+ }
+ )
+ partners_now = self.env['res.partner'].search([]) - partners_before
+ self.assertEqual(len(results['ids']), 3, "should have imported the first 3 records in full, got %s" % results['ids'])
+
+ self.assertEqual(partners_now[0].name, 'foo', "New partner's name should be foo")
+ self.assertEqual(partners_now[0].country_id.id, self.env.ref('base.us').id, "Foo partner's country should be US")
+ self.assertEqual(partners_now[0].company_type, 'person', "Foo partner's country should be person")
+
+ self.assertEqual(partners_now[1].country_id.id, False, "foo1 partner's country should be False")
+
+ self.assertEqual(partners_now[2].company_type, False, "foo2 partner's country should be False")
+ # if results empty, no errors
+ self.assertItemsEqual(results['messages'], [])
+
+ def test_skip_record_import(self):
+ partners_before = self.env['res.partner'].search([])
+ import_wizard = self.env['base_import.import'].create({
+ 'res_model': 'res.partner',
+ 'file': """foo,US,0,person\n
+foo1,Invalid Country,0,person\n
+foo2,US,False Value,person\n
+foo3,US,0,persons\n""",
+ 'file_type': 'text/csv'
+ })
+
+ results = import_wizard.execute_import(
+ ['name', 'country_id', 'is_company', 'company_type'],
+ [],
+ {
+ 'quoting': '"',
+ 'separator': ',',
+ 'import_skip_records': ['country_id', 'is_company', 'company_type']
+ }
+ )
+ partners_now = self.env['res.partner'].search([]) - partners_before
+
+ self.assertEqual(len(results['ids']), 1, "should have imported the first record in full, got %s" % results['ids'])
+ self.assertEqual(partners_now.name, 'foo', "New partner's name should be foo")
+ # if results empty, no errors
+ self.assertItemsEqual(results['messages'], [])
+
class TestBatching(TransactionCase):
def _makefile(self, rows):
diff --git a/addons/base_import/tests/test_csv_magic.py b/addons/base_import/tests/test_csv_magic.py
index 4e693ed32a1..bc4c1d89841 100644
--- a/addons/base_import/tests/test_csv_magic.py
+++ b/addons/base_import/tests/test_csv_magic.py
@@ -67,7 +67,7 @@ class TestEncoding(ImportCase):
})
self.assertIsNone(r.get('error'))
self.assertEqual(r['options']['encoding'], 'iso-8859-1')
- self.assertEqual(r['preview'], [s.decode('iso-8859-1')])
+ self.assertEqual(r['preview'], [[s.decode('iso-8859-1'), 'text']])
class TestFileSeparator(ImportCase):
@@ -90,7 +90,7 @@ d|4
})
self.assertIsNone(r.get('error'))
self.assertEqual(r['headers'], ['c', 'f'])
- self.assertEqual(r['preview'], ['a', '1'])
+ self.assertEqual(r['preview'], [['a', 'b', 'c', 'd'], ['1', '2', '3', '4']])
self.assertEqual(r['options']['separator'], '|')
def test_explicit_fail(self):
@@ -103,7 +103,7 @@ d|4
})
self.assertIsNone(r.get('error'))
self.assertEqual(r['headers'], ['c|f'])
- self.assertEqual(r['preview'], ['a|1'])
+ self.assertEqual(r['preview'], [['a|1', 'b|2', 'c|3', 'd|4']])
self.assertEqual(r['options']['separator'], ',')
def test_guess_ok(self):
@@ -114,7 +114,7 @@ d|4
})
self.assertIsNone(r.get('error'))
self.assertEqual(r['headers'], ['c', 'f'])
- self.assertEqual(r['preview'], ['a', '1'])
+ self.assertEqual(r['preview'], [['a', 'b', 'c', 'd'], ['1', '2', '3', '4']])
self.assertEqual(r['options']['separator'], '|')
def test_noguess(self):
@@ -129,7 +129,7 @@ d|4
})
self.assertIsNone(r.get('error'))
self.assertEqual(r['headers'], ['c'])
- self.assertEqual(r['preview'], ['a'])
+ self.assertEqual(r['preview'], [['a', 'b', 'c', 'd']])
self.assertEqual(r['options']['separator'], '')
diff --git a/odoo/addons/base/models/ir_fields.py b/odoo/addons/base/models/ir_fields.py
index 8dc639b2ee1..f87769b17eb 100644
--- a/odoo/addons/base/models/ir_fields.py
+++ b/odoo/addons/base/models/ir_fields.py
@@ -204,6 +204,9 @@ class IrFieldsConverter(models.AbstractModel):
if value.lower() in falses:
return False, []
+ if field.name in self._context.get('import_skip_records', []):
+ return None, []
+
return True, [self._format_import_error(
ValueError,
_(u"Unknown value '%s' for boolean field '%%(field)s'"),
@@ -319,6 +322,10 @@ class IrFieldsConverter(models.AbstractModel):
if value.lower() == str(item).lower() or any(value.lower() == label.lower() for label in labels):
return item, []
+ if field.name in self._context.get('import_skip_records', []):
+ return None, []
+ elif field.name in self._context.get('import_set_empty_fields', []):
+ return False, []
raise self._format_import_error(
ValueError,
_(u"Value '%s' not found in selection field '%%(field)s'"),
@@ -417,12 +424,14 @@ class IrFieldsConverter(models.AbstractModel):
subfield
)
- import_skip = False
+ set_empty = False
+ skip_record = False
if self.env.context.get('import_file'):
- import_skip_fields = self.env.context.get('import_skip_fields') or []
+ import_set_empty_fields = self.env.context.get('import_set_empty_fields') or []
field_path = "/".join((self.env.context.get('parent_fields_hierarchy', []) + [field.name]))
- import_skip = field_path in import_skip_fields
- if id is None and not import_skip:
+ set_empty = field_path in import_set_empty_fields
+ skip_record = field_path in self.env.context.get('import_skip_records', [])
+ if id is None and not set_empty and not skip_record:
if error_msg:
message = _("No matching record found for %(field_type)s '%(value)s' in field '%%(field)s' and the following error was encountered when we attempted to create one: %(error_message)s")
else:
@@ -516,6 +525,11 @@ class IrFieldsConverter(models.AbstractModel):
ids.append(id)
warnings.extend(ws)
+ if field.name in self._context.get('import_set_empty_fields', []) and any([id is None for id in ids]):
+ ids = [id for id in ids if id]
+ elif field.name in self._context.get('import_skip_records', []) and any([id is None for id in ids]):
+ return None, warnings
+
if self._context.get('update_many2many'):
return [Command.link(id) for id in ids], warnings
else:
diff --git a/odoo/models.py b/odoo/models.py
index f0d92b697f3..6e16adb906d 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -1192,6 +1192,9 @@ class BaseModel(metaclass=MetaModel):
info = {'rows': {'to': -1}}
for id, xid, record, info in converted:
+ if self.env.context.get('import_file') and self.env.context.get('import_skip_records'):
+ if any([record.get(field) is None for field in self.env.context['import_skip_records']]):
+ continue
if xid:
xid = xid if '.' in xid else "%s.%s" % (current_module, xid)
batch_xml_ids.add(xid)