changeset 41bae0ca6718 in trytond:default
details: https://hg.tryton.org/trytond?cmd=changeset&node=41bae0ca6718
description:
        Skip default values when copying records

        This allows users with no write access to a field to copy records if 
their
        values have not been modified.

        issue10536
        review336541002
diffstat:

 CHANGELOG                     |   1 +
 trytond/model/modelstorage.py |  15 ++++++--
 trytond/tests/copy_.py        |  11 ++++++
 trytond/tests/test_copy.py    |  74 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 97 insertions(+), 4 deletions(-)

diffs (185 lines):

diff -r 05235e67b280 -r 41bae0ca6718 CHANGELOG
--- a/CHANGELOG Mon Oct 11 11:52:42 2021 +0200
+++ b/CHANGELOG Mon Oct 11 15:14:57 2021 +0200
@@ -1,3 +1,4 @@
+* Skip default values when copying records
 * Use global cache for Function fields in readonly transactions
 * Add format method to DictSchemaMixin
 * Allow modify record name on the reports
diff -r 05235e67b280 -r 41bae0ca6718 trytond/model/modelstorage.py
--- a/trytond/model/modelstorage.py     Mon Oct 11 11:52:42 2021 +0200
+++ b/trytond/model/modelstorage.py     Mon Oct 11 15:14:57 2021 +0200
@@ -370,7 +370,7 @@
                 for name, value in default.items()
                 if name.startswith(prefix)}
 
-        def convert_data(field_defs, origin):
+        def convert_data(field_defs, origin, default_values):
             data = origin.copy()
             for field_name in field_defs:
                 ftype = field_defs[field_name]['type']
@@ -383,13 +383,16 @@
                         'write_uid',
                         ):
                     del data[field_name]
+                    continue
 
                 if field_name in default:
                     if callable(default[field_name]):
                         data[field_name] = default[field_name](origin)
                     else:
                         data[field_name] = default[field_name]
-                if (isinstance(field, fields.Function)
+                if data[field_name] == default_values.get(field_name):
+                    del data[field_name]
+                elif (isinstance(field, fields.Function)
                         and not isinstance(field, fields.MultiValue)):
                     del data[field_name]
                 elif ftype in ('many2one', 'one2one'):
@@ -433,9 +436,10 @@
         ids = list(map(int, records))
         values = {d['id']: d for d in cls.read(ids, fields_names=fields_names)}
         field_defs = cls.fields_get(fields_names=fields_names)
+        default_values = cls.default_get(fields_names, with_rec_name=False)
         to_create = []
         for id_ in ids:
-            data = convert_data(field_defs, values[id_])
+            data = convert_data(field_defs, values[id_], default_values)
             to_create.append(data)
         new_records = cls.create(to_create)
 
@@ -459,12 +463,15 @@
                     # should be the same.
                     with Transaction().set_context(language=lang.code,
                             fuzzy_translation=False):
+                        default_values = cls.default_get(
+                            fields_names, with_rec_name=False)
                         values = cls.read(ids, fields_names=fields_names)
                         to_write = []
                         for data in values:
                             to_write.append(id2new_records[data['id']])
                             to_write.append(
-                                convert_data(fields_translate, data))
+                                convert_data(
+                                    fields_translate, data, default_values))
                         cls.write(*to_write)
         return new_records
 
diff -r 05235e67b280 -r 41bae0ca6718 trytond/tests/copy_.py
--- a/trytond/tests/copy_.py    Mon Oct 11 11:52:42 2021 +0200
+++ b/trytond/tests/copy_.py    Mon Oct 11 15:14:57 2021 +0200
@@ -101,6 +101,16 @@
     file_id = fields.Char("Binary ID")
 
 
+class CopyAccess(ModelSQL):
+    "Copy with Access"
+    __name__ = 'test.copy.access'
+    name = fields.Char("Name")
+
+    @classmethod
+    def default_name(cls):
+        return "Default"
+
+
 class CopyTranslate(ModelSQL):
     "Copy Translate"
     __name__ = 'test.copy.translate'
@@ -121,5 +131,6 @@
         CopyMany2ManyReferenceTarget,
         CopyMany2ManyReferenceRelation,
         CopyBinary,
+        CopyAccess,
         CopyTranslate,
         module=module, type_='model')
diff -r 05235e67b280 -r 41bae0ca6718 trytond/tests/test_copy.py
--- a/trytond/tests/test_copy.py        Mon Oct 11 11:52:42 2021 +0200
+++ b/trytond/tests/test_copy.py        Mon Oct 11 15:14:57 2021 +0200
@@ -4,6 +4,7 @@
 import unittest
 
 from trytond.model import fields
+from trytond.model.exceptions import AccessError
 from trytond.tests.test_tryton import activate_module, with_transaction
 from trytond.transaction import Transaction
 from trytond.pool import Pool
@@ -198,6 +199,79 @@
         self.assertEqual(record_copy.file_id, record.file_id)
         self.assertEqual(record_copy.binary_id, record.binary_id)
 
+    @with_transaction(context={'_check_access': True})
+    def test_no_acccess_copy_with_custom_value(self):
+        "Test copying field with no access and custom value"
+        pool = Pool()
+        Field = pool.get('ir.model.field')
+        FieldAccess = pool.get('ir.model.field.access')
+        TestAccess = pool.get('test.copy.access')
+
+        record, = TestAccess.create([{'name': 'foo'}])
+
+        field, = Field.search([
+                ('model.model', '=', 'test.copy.access'),
+                ('name', '=', 'name'),
+                ])
+        FieldAccess.create([{
+                    'field': field.id,
+                    'group': None,
+                    'perm_read': True,
+                    'perm_write': False,
+                    }])
+
+        with self.assertRaises(AccessError):
+            new_record, = TestAccess.copy([record])
+
+    @with_transaction(context={'_check_access': True})
+    def test_no_acccess_copy_with_default(self):
+        "Test copying field with no access but default value"
+        pool = Pool()
+        Field = pool.get('ir.model.field')
+        FieldAccess = pool.get('ir.model.field.access')
+        TestAccess = pool.get('test.copy.access')
+
+        field, = Field.search([
+                ('model.model', '=', 'test.copy.access'),
+                ('name', '=', 'name'),
+                ])
+        FieldAccess.create([{
+                    'field': field.id,
+                    'group': None,
+                    'perm_read': True,
+                    'perm_write': False,
+                    }])
+
+        record, = TestAccess.create([{}])
+        self.assertEqual(record.name, "Default")
+        new_record, = TestAccess.copy([record])
+        self.assertEqual(new_record.name, "Default")
+
+    @with_transaction(context={'_check_access': True})
+    def test_no_acccess_copy_with_defaults(self):
+        "Test copying field with no access and defaults"
+        pool = Pool()
+        Field = pool.get('ir.model.field')
+        FieldAccess = pool.get('ir.model.field.access')
+        TestAccess = pool.get('test.copy.access')
+
+        record, = TestAccess.create([{}])
+
+        field, = Field.search([
+                ('model.model', '=', 'test.copy.access'),
+                ('name', '=', 'name'),
+                ])
+        FieldAccess.create([{
+                    'field': field.id,
+                    'group': None,
+                    'perm_read': True,
+                    'perm_write': False,
+                    }])
+
+        with self.assertRaises(AccessError):
+            new_record, = TestAccess.copy(
+                [record], default={'name': 'nondefault'})
+
 
 class CopyTranslationTestCase(TranslationTestCase):
     "Test copy translation"

Reply via email to