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"