[ADD] force linking to existing o2m being updated

bzr revid: xmo@openerp.com-20120920102545-30tkodb4s1dng5hp
This commit is contained in:
Xavier Morel 2012-09-20 12:25:45 +02:00
parent 9805c665c8
commit c9e0cfd64a
2 changed files with 45 additions and 28 deletions

View File

@ -5,6 +5,22 @@ import warnings
from openerp.osv import orm, fields
from openerp.tools.translate import _
REFERENCING_FIELDS = set([None, 'id', '.id'])
def only_ref_fields(record):
return dict((k, v) for k, v in record.iteritems()
if k in REFERENCING_FIELDS)
def exclude_ref_fields(record):
return dict((k, v) for k, v in record.iteritems()
if k not in REFERENCING_FIELDS)
CREATE = lambda values: (0, False, values)
UPDATE = lambda id, values: (1, id, values)
DELETE = lambda id: (2, id, False)
FORGET = lambda id: (3, id, False)
LINK_TO = lambda id: (4, id, False)
DELETE_ALL = lambda: (5, False, False)
REPLACE_WITH = lambda ids: (6, False, ids)
class ConversionNotFound(ValueError): pass
class ir_fields_converter(orm.Model):
@ -145,9 +161,8 @@ class ir_fields_converter(orm.Model):
:rtype: str
"""
# Can import by name_get, external id or database id
allowed_fields = set([None, 'id', '.id'])
fieldset = set(record.iterkeys())
if fieldset - allowed_fields:
if fieldset - REFERENCING_FIELDS:
raise ValueError(
_(u"Can not create Many-To-One records indirectly, import the field separately"))
if len(fieldset) > 1:
@ -190,4 +205,17 @@ class ir_fields_converter(orm.Model):
return [(6, 0, ids)]
def _str_to_one2many(self, cr, uid, model, column, value, context=None):
return value
commands = []
for subfield, record in zip((self._referencing_subfield(
only_ref_fields(record))
for record in value),
value):
id, subfield_type = self.db_id_for(
cr, uid, model, column, subfield, record[subfield], context=context)
writable = exclude_ref_fields(record)
if id:
commands.append(LINK_TO(id))
commands.append(UPDATE(id, writable))
else:
commands.append(CREATE(writable))
return commands

View File

@ -869,10 +869,13 @@ class test_o2m(ImporterCase):
"invalid literal for int() with base 10: '%d,%d'" % (id1, id2))
def test_link(self):
id1 = self.registry('export.one2many.child').create(self.cr, openerp.SUPERUSER_ID, {
""" O2M relating to an existing record (update) force a LINK_TO as well
"""
O2M = self.registry('export.one2many.child')
id1 = O2M.create(self.cr, openerp.SUPERUSER_ID, {
'str': 'Bf', 'value': 109
})
id2 = self.registry('export.one2many.child').create(self.cr, openerp.SUPERUSER_ID, {
id2 = O2M.create(self.cr, openerp.SUPERUSER_ID, {
'str': 'Me', 'value': 262
})
@ -880,17 +883,14 @@ class test_o2m(ImporterCase):
['42', str(id1)],
['', str(id2)],
])
self.assertEqual(len(ids), 2)
self.assertFalse(messages)
self.assertEqual(len(ids), 1)
# No record values alongside id => o2m resolution skipped altogether,
# creates 2 records => remove/don't import columns sideshow columns,
# get completely different semantics
b, b1 = self.browse()
[b] = self.browse()
self.assertEqual(b.const, 42)
self.assertEqual(values(b.value), [])
self.assertEqual(b1.const, 4)
self.assertEqual(values(b1.value), [])
# automatically forces link between core record and o2ms
self.assertEqual(values(b.value), [109, 262])
self.assertEqual(values(b.value, field='parent_id'), [b, b])
def test_link_2(self):
O2M_c = self.registry('export.one2many.child')
@ -905,24 +905,13 @@ class test_o2m(ImporterCase):
['42', str(id1), '1'],
['', str(id2), '2'],
])
self.assertEqual(len(ids), 2)
self.assertFalse(messages)
self.assertEqual(len(ids), 1)
(b,) = self.browse()
# if an id (db or xid) is provided, expectations that objects are
# *already* linked and emits UPDATE (1, id, {}).
# Noid => CREATE (0, ?, {})
# TODO: xid ignored aside from getting corresponding db id?
[b] = self.browse()
self.assertEqual(b.const, 42)
self.assertEqual(values(b.value), [])
# FIXME: updates somebody else's records?
self.assertEqual(
O2M_c.read(self.cr, openerp.SUPERUSER_ID, id1),
{'id': id1, 'str': 'Bf', 'value': 1, 'parent_id': False})
self.assertEqual(
O2M_c.read(self.cr, openerp.SUPERUSER_ID, id2),
{'id': id2, 'str': 'Me', 'value': 2, 'parent_id': False})
self.assertEqual(values(b.value), [1, 2])
self.assertEqual(values(b.value, field='parent_id'), [b, b])
class test_o2m_multiple(ImporterCase):
model_name = 'export.one2many.multiple'