[IMP] ir.edi: improve edi_import_relation and edi_xml_id with better xml_id, uuid

bzr revid: hmo@tinyerp.com-20110829074732-lq2q9k2wh2ywnooy
This commit is contained in:
Harry (OpenERP)
2011-08-29 13:17:32 +05:30
parent 6b111d9b1c
commit 2b0109060c
2 changed files with 58 additions and 61 deletions
+56 -61
View File
@@ -29,8 +29,6 @@ import openerp.release as release
from tools.translate import _
import netsvc
edi_module = 'edi_import'
def safe_unique_id(database_id, model, record_id):
"""Generate a unique string to represent a (database id,model,record_id) pair
without being too long, without revealing the database id, and
@@ -42,7 +40,7 @@ def safe_unique_id(database_id, model, record_id):
# finally, use the b64-encoded folded digest as ID part of the unique ID:
digest = base64.urlsafe_b64encode(digest)
return '%s-%s' % (model,digest)
return '%s-%s' % (model.replace('.','_'), digest)
class ir_edi_document(osv.osv):
_name = 'ir.edi.document'
@@ -185,6 +183,15 @@ class edi(object):
``edi_import()`` and ``edi_export()`` methods to implement their
specific behavior, based on the primitives provided by this superclass."""
def record_xml_id(self, cr, uid, record, context=None):
model_data_pool = self.pool.get('ir.model.data')
data_ids = model_data_pool.search(cr, uid, [('res_id','=',record.id),('model','=',record._name)])
if not data_ids:
return False
xml_record_id = data_ids[0]
xml_record = model_data_pool.browse(cr, uid, xml_record_id, context=context)
return xml_record.module, xml_record.name
def edi_xml_id(self, cr, uid, record, context=None):
"""
Generate a unique string to represent a pair of (the database's UUID, the XML ID).
@@ -206,20 +213,21 @@ class edi(object):
model_data_pool = self.pool.get('ir.model.data')
db_uuid = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid')
data_ids = model_data_pool.search(cr, uid, [('res_id','=',record.id),('model','=',record._name)])
if len(data_ids):
xml_record_id = data_ids[0]
xml_record = model_data_pool.browse(cr, uid, xml_record_id, context=context)
uuid = '%s:%s' % (db_uuid, xml_record.name)
_record_xml = self.record_xml_id(cr, uid, record, context=context)
if _record_xml:
module, xml_id = _record_xml
xml_id = '%s:%s.%s' % (db_uuid, module, xml_id)
else:
xml_id = safe_unique_id(db_uuid, record._name, record.id)
uuid = '%s:%s' % (db_uuid, xml_id)
uuid = safe_unique_id(db_uuid, record._name, record.id)
xml_id = '%s:%s.%s' % (db_uuid, record._module, uuid)
assert len(xml_id.split('.'))==2, _("'%s' contains too many dots. XML ids should not contain dots ! These are used to refer to other modules data, as in module.reference_id") % (xml_id)
module, xml_id2 = xml_id.split('.')
xml_record_id = model_data_pool.create(cr, uid, {
'name': xml_id,
'name': xml_id2,
'model': record._name,
'module': uuid,
'module': module,
'res_id': record.id}, context=context)
return uuid
return xml_id
def edi_metadata(self, cr, uid, records, context=None):
"""Return a list representing the boilerplate EDI structure for
@@ -385,14 +393,29 @@ class edi(object):
edi_dict_list.append(edi_dict)
return edi_dict_list
def edi_import_relation(self, cr, uid, relation_model, relation_value, values={}, context=None):
def edi_import_relation(self, cr, uid, relation_model, relation_value, xml_id=None, context=None):
relation_id = False
model_data = self.pool.get('ir.model.data')
relation_object = self.pool.get(relation_model)
relation_ids = relation_object.name_search(cr, uid, relation_value, context=context)
if relation_ids and len(relation_ids) == 1:
relation_id = relation_ids[0][0]
else:
values.update({'name': relation_value})
values = {relation_object._rec_name: relation_value}
if not relation_id:
relation_id = relation_object.create(cr, uid, values, context=context)
relation_record = relation_object.browse(cr, uid, relation_id, context=context)
record_xml = self.record_xml_id(cr, uid, relation_record, context=context)
if record_xml:
module, xml_id = record_xml
xml_id = '%s.%s' % (module, xml_id)
if not xml_id:
xml_id = self.edi_xml_id(cr, uid, relation_record, context=context)
if xml_id:
assert len(xml_id.split('.'))==2, _("'%s' contains too many dots. XML ids should not contain dots ! These are used to refer to other modules data, as in module.reference_id") % (xml_id)
module, xml_id2 = xml_id.split('.')
#TODO: update record from values
#relation_id = model_data._update(cr, uid, relation_model, module, values, xml_id=xml_id, context=context)
return relation_id
def edi_import(self, cr, uid, edi_document, context=None):
@@ -443,24 +466,28 @@ class edi(object):
connect it to the parent record via a write value like (4, db_id).
"""
# generic implementation!
fields = edi_document.keys()
fields_to_import = []
data_line = []
model_data = self.pool.get('ir.model.data')
_fields = self.fields_get(cr, uid, context=context)
values = {}
xml_id = edi_document['__id']
assert len(xml_id.split('.'))==2, _("'%s' contains too many dots. XML ids should not contain dots ! These are used to refer to other modules data, as in module.reference_id") % (xml_id)
module, xml_id2 = xml_id.split('.')
for field in edi_document.keys():
if not field.startswith('__'):
fields_to_import.append(field)
edi_field_value = edi_document[field]
field_type = _fields[field]['type']
relation_model = _fields[field].get('relation')
if not edi_field_value:
continue
if _fields[field].has_key('function') or _fields[field].has_key('related_columns'):
# DO NOT IMPORT FUNCTION FIELD AND RELATED FIELD
continue
elif _fields[field]['type'] in ('many2one', 'many2many'):
if _fields[field]['type'] == 'many2one':
elif field_type in ('many2one', 'many2many'):
if field_type == 'many2one':
edi_parent_documents = [edi_field_value]
else:
edi_parent_documents = edi_field_value
@@ -468,41 +495,19 @@ class edi(object):
parent_lines = []
for edi_parent_document in edi_parent_documents:
#Look in ir.model.data for a record that matches the db_id.
#If found, replace the m2o value with the correct database ID and stop.
#If not found, continue to next step
xml_id = edi_parent_document[0]
data_ids = model_data.name_search(cr, uid, xml_id)
if data_ids:
for data in model_data.browse(cr, uid, [data_ids[0][0]], context=context):
parent_lines.append(data.res_id)
else:
#Perform name_search(name) to look for a record that matches the
#given m2o name. If only one record is found, create the missing
#ir.model.data record to link it to the db_id, and the replace the m2o
#value with the correct database ID, then stop. If zero result or
#multiple results are found, go to next step.
#Create the new record using the only field value that is known: the
#name, and create the ir.model.data entry to map to it.
relation_model = _fields[field]['relation']
relation_id = self.edi_import_relation(cr, uid, relation_model, edi_parent_document[1], context=context)
relation_object = self.pool.get(relation_model)
relation_record = relation_object.browse(cr, uid, relation_id, context=context)
self.edi_xml_id(cr, uid, relation_record, context=context)
parent_lines.append(relation_id)
relation_id = self.edi_import_relation(cr, uid, relation_model, edi_parent_document[1], edi_parent_document[0], context=context)
parent_lines.append(relation_id)
if len(parent_lines):
if _fields[field]['type'] == 'many2one':
if field_type == 'many2one':
values[field] = parent_lines[0]
else:
many2many_ids = []
for m2m_id in parent_lines:
many2many_ids.append((4,m2m_id))
many2many_ids.append((4, m2m_id))
values[field] = many2many_ids
elif _fields[field]['type'] == 'one2many':
elif field_type == 'one2many':
#Look for a record that matches the db_id provided in the __id field. If
#found, keep the corresponding database id, and connect it to the parent
#using a write value like (4,db_id).
@@ -511,22 +516,12 @@ class edi(object):
#and use it to connect to the parent via a write value like (4, db_id).
relations = []
relation_object = self.pool.get(_fields[field]['relation'])
relation_object = self.pool.get(relation_model)
for edi_relation_document in edi_field_value:
if edi_relation_document['__id'].find(':') != -1:
db_uuid, xml_id = tuple(edi_relation_document['__id'].split(':'))
data_ids = model_data.name_search(cr, uid, xml_id)
if data_ids:
for data in model_data.browse(cr,uid,[data_ids[0][0]]):
relations.append(data.res_id)
else:
r = relation_object.edi_import(cr, uid, edi_relation_document, context=context)
relations.append(r)
one2many_ids = []
for o2m_id in relations:
one2many_ids.append((4,o2m_id))
values[field] = one2many_ids
relation_id = relation_object.edi_import(cr, uid, edi_relation_document, context=context)
relations.append((4, relation_id))
values[field] = relations
else:
values[field] = edi_field_value
return model_data._update(cr, uid, self._name, edi_module, values, context=context)
return model_data._update(cr, uid, self._name, module, values, xml_id=xml_id, context=context)
# vim: ts=4 sts=4 sw=4 si et
+2
View File
@@ -63,6 +63,7 @@ class edi(netsvc.ExportService):
res = edi_pool.import_edi(cr, uid, edi_document=edi_document, context=context)
cr.commit()
except:
print traceback.format_exc()
cr.rollback()
finally:
cr.close()
@@ -77,6 +78,7 @@ class edi(netsvc.ExportService):
res = edi_pool.import_edi(cr, uid, edi_url=edi_url, context=context)
cr.commit()
except:
print traceback.format_exc()
cr.rollback()
finally:
cr.close()