diff --git a/modules/account/account.py b/modules/account/account.py index 89dbbd3d3f..71c1dc4795 100644 --- a/modules/account/account.py +++ b/modules/account/account.py @@ -1274,7 +1274,7 @@ class Account( else: default = default.copy() default.setdefault('template', None) - default.setdefault('deferrals', []) + default.setdefault('deferrals') new_accounts = super().copy(accounts, default=default) cls._rebuild_tree('parent', None, 0) return new_accounts diff --git a/modules/account/move.py b/modules/account/move.py index 62b6d3e2f0..5e4e579a81 100644 --- a/modules/account/move.py +++ b/modules/account/move.py @@ -1571,7 +1571,7 @@ class Line(DescriptionOriginMixin, MoveLineMixin, ModelSQL, ModelView): default.setdefault('state', 'draft') default.setdefault('move', None) default.setdefault('reconciliation', None) - default.setdefault('reconciliations_delegated', []) + default.setdefault('reconciliations_delegated') return super().copy(lines, default=default) @classmethod diff --git a/modules/account_asset/asset.py b/modules/account_asset/asset.py index 04bbaffd55..d01732c734 100644 --- a/modules/account_asset/asset.py +++ b/modules/account_asset/asset.py @@ -728,12 +728,12 @@ class Asset(Workflow, ModelSQL, ModelView): default = {} else: default = default.copy() - default.setdefault('lines', []) - default.setdefault('update_moves', []) + default.setdefault('lines') + default.setdefault('update_moves') default.setdefault('number', None) default.setdefault('supplier_invoice_line', None) default.setdefault('move') - default.setdefault('revisions', []) + default.setdefault('revisions') return super().copy(assets, default=default) @classmethod diff --git a/modules/account_payment_stripe/payment.py b/modules/account_payment_stripe/payment.py index 4a95c0c98e..e2e12a1411 100644 --- a/modules/account_payment_stripe/payment.py +++ b/modules/account_payment_stripe/payment.py @@ -282,10 +282,6 @@ class Payment(StripeCustomerMethodMixin, CheckoutMixin, metaclass=PoolMeta): def default_stripe_capturable(cls): return False - @classmethod - def default_stripe_idempotency_key(cls): - return uuid.uuid4().hex - @fields.depends('process_method', 'stripe_token', 'stripe_payment_intent_id', 'stripe_customer_source', 'stripe_customer_source_selection', @@ -349,9 +345,7 @@ class Payment(StripeCustomerMethodMixin, CheckoutMixin, metaclass=PoolMeta): if mode == 'create': if 'stripe_idempotency_key' not in values: # Ensure to get a different key for each record - # default methods are called only once - values['stripe_idempotency_key'] = ( - cls.default_stripe_idempotency_key()) + values['stripe_idempotency_key'] = uuid.uuid4().hex return values @classmethod @@ -843,10 +837,6 @@ class Refund(Workflow, ModelSQL, ModelView): def get_stripe_amount(self, name): return int(self.amount * 10 ** self.currency.digits) - @classmethod - def default_stripe_idempotency_key(cls): - return uuid.uuid4().hex - @fields.depends('payment', '_parent_payment.currency') def on_change_with_currency(self, name=None): return self.payment.currency if self.payment else None @@ -865,9 +855,7 @@ class Refund(Workflow, ModelSQL, ModelView): if mode == 'create': if 'stripe_idempotency_key' not in values: # Ensure to get a different key for each record - # default methods are called only once - values['stripe_idempotency_key'] = ( - cls.default_stripe_idempotency_key()) + values['stripe_idempotency_key'] = uuid.uuid4().hex return values @classmethod diff --git a/modules/party/party.py b/modules/party/party.py index b2ac705813..52a70c3ba4 100644 --- a/modules/party/party.py +++ b/modules/party/party.py @@ -968,6 +968,10 @@ class Identifier(sequence_ordered(), DeactivableMixin, ModelSQL, ModelView): pass return code + @classmethod + def default_eu_vat_valid(cls): + return False + def pre_validate(self): super().pre_validate() self.check_code() @@ -1076,7 +1080,7 @@ class Identifier(sequence_ordered(), DeactivableMixin, ModelSQL, ModelView): @classmethod def copy(cls, identifiers, default=None): default = default.copy() if default is not None else {} - default.setdefault('eu_vat_valid') + default.setdefault('eu_vat_valid', cls.default_eu_vat_valid()) default.setdefault('eu_vat_validated_at') return super().copy(identifiers, default=default) diff --git a/modules/sale_advance_payment/sale.py b/modules/sale_advance_payment/sale.py index 2dfce7f45a..e0a4446faa 100644 --- a/modules/sale_advance_payment/sale.py +++ b/modules/sale_advance_payment/sale.py @@ -223,7 +223,7 @@ class AdvancePaymentLine(ModelSQL, ModelView): default = {} else: default = default.copy() - default.setdefault('invoice_lines', []) + default.setdefault('invoice_lines') return super().copy(lines, default) def create_invoice(self): diff --git a/modules/sale_project_task/sale.py b/modules/sale_project_task/sale.py index f0374838b0..174050b133 100644 --- a/modules/sale_project_task/sale.py +++ b/modules/sale_project_task/sale.py @@ -128,6 +128,10 @@ class Sale(metaclass=PoolMeta): return Configuration(1).get_multivalue( 'sale_task_creation_method', **pattern) + @classmethod + def default_tasks_to_create(cls): + return False + @classmethod def check_method(cls, sales, field_names=None): super().check_method(sales, field_names=field_names) @@ -148,7 +152,7 @@ class Sale(metaclass=PoolMeta): def copy(cls, sales, default=None): default = default.copy() if default is not None else {} default.setdefault('tasks_state') - default.setdefault('tasks_to_create') + default.setdefault('tasks_to_create', cls.default_tasks_to_create()) return super().copy(sales, default=default) @classmethod diff --git a/trytond/trytond/model/modelsingleton.py b/trytond/trytond/model/modelsingleton.py index b88ca7e1b6..a0eef5bf89 100644 --- a/trytond/trytond/model/modelsingleton.py +++ b/trytond/trytond/model/modelsingleton.py @@ -114,12 +114,17 @@ class ModelSingleton(ModelStorage): return res @classmethod - def default_get(cls, fields_names, with_rec_name=True): + def default_get( + cls, fields_names=None, with_rec_name=True, with_default=True): + if fields_names is None: + fields_names = cls._fields.keys() + if '_timestamp' in fields_names: fields_names = list(fields_names) fields_names.remove('_timestamp') - default = super().default_get(fields_names, - with_rec_name=with_rec_name) + default = super().default_get( + fields_names, + with_rec_name=with_rec_name, with_default=with_default) singleton = cls.get_singleton() if singleton: if with_rec_name: diff --git a/trytond/trytond/tests/test_tryton.py b/trytond/trytond/tests/test_tryton.py index 5004009c33..65789c26e2 100644 --- a/trytond/trytond/tests/test_tryton.py +++ b/trytond/trytond/tests/test_tryton.py @@ -927,6 +927,7 @@ class ModuleTestCase(DBTestCase): continue if not issubclass(model, ModelStorage): continue + default_values = model.default_get(with_rec_name=False) with self.subTest(model=mname): model.copy([]) if copy.call_args: @@ -939,6 +940,13 @@ class ModuleTestCase(DBTestCase): fields = { k.split('.', 1)[0] for k in default.keys()} self.assertLessEqual(fields, klass._fields.keys()) + for field_name in fields: + field = getattr(klass, field_name) + if field.readonly: + with self.subTest(field=field_name): + self.assertEqual( + default[field_name], + default_values.get(field_name)) copy.reset_mock() @with_transaction()