diff --git a/base_import_odoo/__openerp__.py b/base_import_odoo/__openerp__.py
index 31191330d..fdd6f8f7f 100644
--- a/base_import_odoo/__openerp__.py
+++ b/base_import_odoo/__openerp__.py
@@ -12,6 +12,7 @@
'base',
],
"demo": [
+ "demo/res_partner.xml",
"demo/res_users.xml",
"demo/ir_attachment.xml",
"demo/import_odoo_database.xml",
diff --git a/base_import_odoo/demo/res_partner.xml b/base_import_odoo/demo/res_partner.xml
new file mode 100644
index 000000000..50c1b2a99
--- /dev/null
+++ b/base_import_odoo/demo/res_partner.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/base_import_odoo/models/import_odoo_database.py b/base_import_odoo/models/import_odoo_database.py
index 684bf0fbc..3965dd49f 100644
--- a/base_import_odoo/models/import_odoo_database.py
+++ b/base_import_odoo/models/import_odoo_database.py
@@ -11,6 +11,7 @@ import traceback
from urlparse import urlparse
from openerp import _, api, exceptions, fields, models, tools
from collections import namedtuple
+_logger = logging.getLogger('base_import_odoo')
import_context_tuple = namedtuple(
@@ -116,6 +117,7 @@ class ImportOdooDatabase(models.Model):
'counts': remote_counts,
'ids': remote_ids,
'error': None,
+ 'dummies': None,
'done': {},
}
})
@@ -151,9 +153,17 @@ class ImportOdooDatabase(models.Model):
raise
done[model._name] += len(ids)
self.write({'status_data': dict(self.status_data, done=done)})
+
if commit and not tools.config['test_enable']:
# pylint: disable=invalid-commit
self.env.cr.commit()
+ missing = {}
+ for dummy_model, remote_id in dummies.keys():
+ if remote_id:
+ missing.setdefault(dummy_model, []).append(remote_id)
+ self.write({
+ 'status_data': dict(self.status_data, dummies=dict(missing)),
+ })
@api.multi
def _run_import_model(self, context):
@@ -163,7 +173,9 @@ class ImportOdooDatabase(models.Model):
for data in context.remote.execute(
model._name, 'read', context.ids, fields.keys()
):
- self._run_import_get_record(context, model, data)
+ self._run_import_get_record(
+ context, model, data, create_dummy=False,
+ )
if (model._name, data['id']) in context.idmap:
# there's a mapping for this record, nothing to do
continue
@@ -179,13 +191,14 @@ class ImportOdooDatabase(models.Model):
"""Create a record, add an xmlid"""
_id = record.pop('id')
xmlid = '%d-%s-%d' % (
- self.id, model._name.replace('.', '_'), _id,
+ self.id, model._name.replace('.', '_'), _id or 0,
)
if self.env.ref('base_import_odoo.%s' % xmlid, False):
new = self.env.ref('base_import_odoo.%s' % xmlid)
new.with_context(
**self._create_record_context(model, record)
).write(record)
+ _logger.debug('Updated record %s', xmlid)
else:
new = model.with_context(
**self._create_record_context(model, record)
@@ -199,6 +212,7 @@ class ImportOdooDatabase(models.Model):
'import_database_id': self.id,
'import_database_record_id': _id,
})
+ _logger.debug('Created record %s', xmlid)
context.idmap[mapping_key(model._name, _id)] = new.id
return new
@@ -218,16 +232,28 @@ class ImportOdooDatabase(models.Model):
"""Find the local id of some remote record. Create a dummy if not
available"""
_id = context.idmap.get((model._name, record['id']))
+ logged = False
if not _id:
_id = context.dummies.get((model._name, record['id']))
if _id:
context.dummy_instances.append(
dummy_instance(*(context.field_context + (_id,)))
)
+ else:
+ logged = True
+ _logger.debug(
+ 'Got %s(%d[%d]) from idmap', model._model, _id,
+ record['id'] or 0,
+ )
if not _id:
_id = self._run_import_get_record_mapping(
context, model, record, create_dummy=create_dummy,
)
+ elif not logged:
+ logged = True
+ _logger.debug(
+ 'Got %s(%d[%d]) from dummies', model._model, _id, record['id'],
+ )
if not _id:
xmlid = self.env['ir.model.data'].search([
('import_database_id', '=', self.id),
@@ -237,8 +263,22 @@ class ImportOdooDatabase(models.Model):
if xmlid:
_id = xmlid.res_id
context.idmap[(model._name, record['id'])] = _id
+ elif not logged:
+ logged = True
+ _logger.debug(
+ 'Got %s(%d[%d]) from mappings',
+ model._model, _id, record['id'],
+ )
if not _id and create_dummy:
- _id = self._run_import_create_dummy(context, model, record)
+ _id = self._run_import_create_dummy(
+ context, model, record,
+ forcecreate=record['id'] not in
+ self.status_data['ids'].get(model._name, [])
+ )
+ elif _id and not logged:
+ _logger.debug(
+ 'Got %s(%d[%d]) from xmlid', model._model, _id, record['id'],
+ )
return _id
@api.multi
@@ -270,9 +310,19 @@ class ImportOdooDatabase(models.Model):
elif mapping.mapping_type == 'by_field':
assert mapping.field_ids
if len(record) == 1:
- continue
+ # just the id of a record we haven't seen yet.
+ # read the whole record from remote to check if
+ # this can be mapped to an existing record
+ record = context.remote.execute(
+ model._name, 'read', record['id'],
+ mapping.field_ids.mapped('name'),
+ ) or None
+ if not record:
+ continue
+ if isinstance(record, list):
+ record = record[0]
records = model.search([
- (field.name, '=', record[field.name])
+ (field.name, '=', record.get(field.name))
for field in mapping.field_ids
], limit=1)
if records:
@@ -310,6 +360,13 @@ class ImportOdooDatabase(models.Model):
context.dummy_instances.append(
dummy_instance(*(context.field_context + (dummy.id,)))
)
+ _logger.debug(
+ 'Using %d as dummy for %s(%d[%d]).%s[%d]',
+ dummy.id, context.field_context.record_model,
+ context.idmap.get(context.field_context.record_id, 0),
+ context.field_context.record_id,
+ context.field_context.field_name, record['id'],
+ )
return dummy.id
required = [
name
@@ -331,6 +388,8 @@ class ImportOdooDatabase(models.Model):
elif model._fields[name].type in ['date', 'datetime']:
value = '2000-01-01'
elif field.type in ['many2one']:
+ if name in model._inherits.values():
+ continue
new_context = context.with_field_context(
model._name, name, record['id']
)
@@ -345,12 +404,20 @@ class ImportOdooDatabase(models.Model):
value = field.selection(model)[0][0]
values[name] = value
dummy = self._create_record(context, model, values)
+ del context.idmap[mapping_key(model._name, record['id'])]
context.dummies[mapping_key(model._name, record['id'])] = dummy.id
context.to_delete.setdefault(model._name, [])
context.to_delete[model._name].append(dummy.id)
context.dummy_instances.append(
dummy_instance(*(context.field_context + (dummy.id,)))
)
+ _logger.debug(
+ 'Created %d as dummy for %s(%d[%d]).%s[%d]',
+ dummy.id, context.field_context.record_model,
+ context.idmap.get(context.field_context.record_id, 0),
+ context.field_context.record_id or 0,
+ context.field_context.field_name, record['id'],
+ )
return dummy.id
@api.multi
@@ -378,7 +445,7 @@ class ImportOdooDatabase(models.Model):
new_context, comodel, {'id': _id},
create_dummy=model._fields[field_name].required or
any(
- m.model_id._name == comodel._name
+ m.model_id.model == comodel._name
for m in self.import_line_ids
),
)
@@ -440,22 +507,28 @@ class ImportOdooDatabase(models.Model):
def _run_import_model_cleanup_dummies(
self, context, model, remote_id, local_id
):
+ if not (model._name, remote_id) in context.dummies:
+ return
for instance in context.dummy_instances:
- if (
- instance.model_name != model._name or
- instance.remote_id != remote_id
- ):
+ key = mapping_key(instance.model_name, instance.remote_id)
+ if key not in context.idmap:
continue
- if not context.idmap.get(instance.remote_id):
+ dummy_id = context.dummies[(model._name, remote_id)]
+ record_model = self.env[instance.model_name]
+ comodel = record_model._fields[instance.field_name].comodel_name
+ if comodel != model._name or instance.dummy_id != dummy_id:
continue
- model = self.env[instance.model_name]
- record = model.browse(context.idmap[instance.remote_id])
- field_name = instance.field_id.name
+ record = record_model.browse(context.idmap[key])
+ field_name = instance.field_name
+ _logger.debug(
+ 'Replacing dummy %d on %s(%d).%s with %d',
+ dummy_id, record_model._name, record.id, field_name, local_id,
+ )
if record._fields[field_name].type == 'many2one':
record.write({field_name: local_id})
elif record._fields[field_name].type == 'many2many':
record.write({field_name: [
- (3, context.idmap[remote_id]),
+ (3, dummy_id),
(4, local_id),
]})
else:
@@ -464,10 +537,11 @@ class ImportOdooDatabase(models.Model):
record._fields[field_name].type
)
context.dummy_instances.remove(instance)
- dummy_id = context.dummies[(record._model, remote_id)]
if dummy_id in context.to_delete:
model.browse(dummy_id).unlink()
- del context.dummies[(record._model, remote_id)]
+ _logger.debug('Deleting dummy %d', dummy_id)
+ if (model._name, remote_id) in context.dummies:
+ del context.dummies[(model._name, remote_id)]
def _get_connection(self):
self.ensure_one()
diff --git a/base_import_odoo/views/import_odoo_database.xml b/base_import_odoo/views/import_odoo_database.xml
index c919798c9..ab8333a8d 100644
--- a/base_import_odoo/views/import_odoo_database.xml
+++ b/base_import_odoo/views/import_odoo_database.xml
@@ -76,6 +76,16 @@
+
+ The following remote ids don't have a mapping but have to be imported anyways due to not null constraints.
+
+
+
+
+
+
+ To fix this, create mappings for the remote ids listed, or if this is not feasible, map the whole model. You might also have a too specific domain on your import model definition.
+