From b477784c0a6034dc00b1ee8d30c2d78881176f82 Mon Sep 17 00:00:00 2001
From: Alexandre Boeglin <alex@nexedi.com>
Date: Thu, 26 Oct 2006 12:58:56 +0000
Subject: [PATCH] When acquired content is set locally (when edited through a
 web form), make sure all properties are copied... Unit test explains it
 better.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@10963 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5/tests/testERP5HR.py              | 27 +++++++++++++-
 product/ERP5Type/Accessor/AcquiredProperty.py |  4 +-
 product/ERP5Type/Accessor/ContentProperty.py  |  1 +
 product/ERP5Type/Base.py                      | 37 ++++++++++++++-----
 4 files changed, 57 insertions(+), 12 deletions(-)

diff --git a/product/ERP5/tests/testERP5HR.py b/product/ERP5/tests/testERP5HR.py
index da8e603e0c..64df3030a7 100644
--- a/product/ERP5/tests/testERP5HR.py
+++ b/product/ERP5/tests/testERP5HR.py
@@ -706,10 +706,35 @@ class TestHR(ERP5TypeTestCase):
     person = sequence.get('person')
     organisation = sequence.get('organisation')
     self.assertEquals(organisation.getDefaultAddressCity(),'Lille')
+    self.assertEquals(organisation.getDefaultAddressZipCode(), '59000')
     self.assertEquals(person.getDefaultAddressCity(),'Lille')
-    person.setDefaultAddressCity('La Garnache')
+    self.assertEquals(person.getDefaultAddressZipCode(), '59000')
+
+    # here, the parameters we pass to edit are the same as the one acquired
+    # from the organisation, edit shouldn't do anything
+    person.edit(
+        default_address_city='Lille',
+        default_address_zip_code='59000')
+
+    self.assertEquals(person.getDefaultAddress(),
+        organisation.getDefaultAddress())
+    self.assertEquals(person.getDefaultAddressCity(),'Lille')
+    self.assertEquals(person.getDefaultAddressZipCode(), '59000')
+
+    # here, the first parameter we pass will trigger the creation of a
+    # subobject on person, and we need to make sure that the second one gets
+    # copied (when calling edit from the interface, all displayed fields are
+    # passed to edit)
+    person.edit(
+        default_address_city='La Garnache',
+        default_address_zip_code='59000')
+
+    self.assertNotEquals(person.getDefaultAddress(),
+        organisation.getDefaultAddress())
     self.assertEquals(person.getDefaultAddressCity(),'La Garnache')
+    self.assertEquals(person.getDefaultAddressZipCode(), '59000')
     self.assertEquals(organisation.getDefaultAddressCity(),'Lille')
+    self.assertEquals(organisation.getDefaultAddressZipCode(), '59000')
 
   ##################################
   ##  Tests
diff --git a/product/ERP5Type/Accessor/AcquiredProperty.py b/product/ERP5Type/Accessor/AcquiredProperty.py
index 4a6125cc35..b7dce91cc9 100644
--- a/product/ERP5Type/Accessor/AcquiredProperty.py
+++ b/product/ERP5Type/Accessor/AcquiredProperty.py
@@ -156,7 +156,9 @@ class Setter(Method):
       assertAttributePortalType(instance, self._storage_id, self._portal_type)
       o = instance._getOb(self._storage_id, None)
       if o is None:
-        o = instance.newContent(id = self._storage_id, portal_type = self._portal_type[0])
+        o = instance.newContent(id=self._storage_id,
+            portal_type=self._portal_type[0])
+        instance._v_accessor_created_object = 1
       if self._reindex:
         o.setProperty(self._acquired_property, value, *args, **kw)
       else:
diff --git a/product/ERP5Type/Accessor/ContentProperty.py b/product/ERP5Type/Accessor/ContentProperty.py
index 71ef13cc6b..e3b5105075 100644
--- a/product/ERP5Type/Accessor/ContentProperty.py
+++ b/product/ERP5Type/Accessor/ContentProperty.py
@@ -220,6 +220,7 @@ class Setter(Method):
         assertAttributePortalType(instance, available_id, self._portal_type)
         o = instance.newContent(id=available_id,
                                 portal_type=self._portal_type[0])
+        instance._v_accessor_created_object = 1
         if self._reindex:
           o.setProperty(self._acquired_property, *args, **kw)
         else:
diff --git a/product/ERP5Type/Base.py b/product/ERP5Type/Base.py
index 948b95d215..c9d2c3e6cb 100644
--- a/product/ERP5Type/Base.py
+++ b/product/ERP5Type/Base.py
@@ -1018,11 +1018,15 @@ class Base( CopyContainer,
 
       Each time attributes of an object are updated, they should
       be updated through this generic edit method
+
+      Modification date is supported by edit_workflow in ERP5
+      There is no need to change it here
     """
     self._v_modified_property_dict = {}
-    my_modified_property_list = []
-    for key in kw.keys():
-      if key != 'id':
+
+    def getModifiedPropertyList(self):
+      my_modified_property_list = []
+      for key in kw.keys():
         # We only change if the value is different
         # This may be very long...
         old_value = None
@@ -1032,7 +1036,6 @@ class Base( CopyContainer,
           except TypeError:
             old_value = self.getProperty(key)
 
-
         if old_value != kw[key] or force_update:
           # We keep in a thread var the previous values
           # this can be useful for interaction workflow to implement lookups
@@ -1040,12 +1043,26 @@ class Base( CopyContainer,
           # edit itself, this is useless as the dict will be overwritten
           self._v_modified_property_dict[key] = old_value
           my_modified_property_list.append(key)
-      elif self.id != kw['id']:
-        self.setId(kw['id'], reindex=reindex_object)
-    # Modification date is supported by edit_workflow in ERP5
-    # There is no need to change it here
-    for key in my_modified_property_list:
-      self._setProperty(key, kw[key])
+      return my_modified_property_list
+
+    my_modified_property_list = getModifiedPropertyList(self)
+
+    # When we get notified by an accessor that it created an object, recheck
+    # all properties
+    while 1:
+      self._v_accessor_created_object = 0
+      for key in my_modified_property_list:
+        if key != 'id':
+          self._setProperty(key, kw[key])
+        else:
+          self.setId(kw['id'], reindex=reindex_object)
+        if self._v_accessor_created_object == 1:
+          # refresh list of modified properties, and restart the process
+          my_modified_property_list = getModifiedPropertyList(self)
+          break
+      else:
+        break
+
     if reindex_object:
       # We do not want to reindex the object if nothing is changed
       if (self._v_modified_property_dict != {}):
-- 
2.30.9