diff --git a/CHANGELOG b/CHANGELOG index 325b864912..90e14a17bf 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ * Add cached_property in tools * Use custom class to store record data +* Do not write to existing targets on xxx2Many add * Add configuration check * Add support for properties to fields.depends * Allow combining authentication methods together diff --git a/trytond/model/fields/one2many.py b/trytond/model/fields/one2many.py index d0155b0a4d..14145e1d5c 100644 --- a/trytond/model/fields/one2many.py +++ b/trytond/model/fields/one2many.py @@ -173,6 +173,14 @@ class One2Many(Field): else: return record_id + def target_value(record): + if record is None: + return None + if field._type == 'reference': + return str(record) + else: + return record.id + def create(ids, vlist): for record_id in ids: value = field_value(record_id) @@ -195,9 +203,13 @@ class One2Many(Field): return targets = Target.browse(target_ids) for record_id in ids: - to_write.extend((targets, { - self.field: field_value(record_id), - })) + fvalue = field_value(record_id) + to_update = [t for t in targets + if target_value(getattr(t, self.field)) != fvalue] + if to_update: + to_write.extend((to_update, { + self.field: fvalue, + })) def remove(ids, target_ids): target_ids = list(map(int, target_ids)) diff --git a/trytond/tests/test_field_many2many.py b/trytond/tests/test_field_many2many.py index 5008295b33..8a42d44043 100644 --- a/trytond/tests/test_field_many2many.py +++ b/trytond/tests/test_field_many2many.py @@ -309,6 +309,25 @@ class CommonTestCaseMixin: self.assertTupleEqual(many2many.targets, (target2,)) self.assertListEqual(targets, [target2]) + @with_transaction() + def test_write_not_readd(self): + "Test write many2many do not re-add existing" + pool = Pool() + Many2Many = self.Many2Many() + Relation = pool.get(Many2Many.targets.relation_name) + many2many, = Many2Many.create([{ + 'targets': [('create', [{}])], + }]) + + target, = many2many.targets + + Many2Many.write([many2many], { + 'targets': [('add', {target.id})], + }) + + relation, = Relation.search([]) + self.assertIsNone(relation.write_date) + class FieldMany2ManyTestCase(unittest.TestCase, CommonTestCaseMixin): "Test Field Many2Many" diff --git a/trytond/tests/test_field_one2many.py b/trytond/tests/test_field_one2many.py index 9366b0c825..7abe51490a 100644 --- a/trytond/tests/test_field_one2many.py +++ b/trytond/tests/test_field_one2many.py @@ -370,6 +370,23 @@ class CommonTestCaseMixin: self.assertTupleEqual(one2many.targets, (target2,)) self.assertListEqual(targets, [target2]) + @with_transaction() + def test_write_not_readd(self): + "Test write one2many do not re-add existing" + One2Many = self.One2Many() + one2many, = One2Many.create([{ + 'targets': [('create', [{}])], + }]) + + target, = one2many.targets + + One2Many.write([one2many], { + 'targets': [('add', {target.id})], + }) + + target, = one2many.targets + self.assertIsNone(target.write_date) + class FieldOne2ManyTestCase(unittest.TestCase, CommonTestCaseMixin): "Test Field One2Many"