diff --git a/InvenTree/InvenTree/api_tester.py b/InvenTree/InvenTree/api_tester.py index a803e6797f..1cbc62ec0a 100644 --- a/InvenTree/InvenTree/api_tester.py +++ b/InvenTree/InvenTree/api_tester.py @@ -18,6 +18,7 @@ class InvenTreeAPITestCase(APITestCase): email = 'test@testing.com' superuser = False + is_staff = True auto_login = True # Set list of roles automatically associated with the user @@ -40,8 +41,12 @@ class InvenTreeAPITestCase(APITestCase): if self.superuser: self.user.is_superuser = True - self.user.save() + if self.is_staff: + self.user.is_staff = True + + self.user.save() + for role in self.roles: self.assignRole(role) diff --git a/InvenTree/InvenTree/serializers.py b/InvenTree/InvenTree/serializers.py index 9e8e811b90..c00c9ef690 100644 --- a/InvenTree/InvenTree/serializers.py +++ b/InvenTree/InvenTree/serializers.py @@ -59,10 +59,47 @@ class InvenTreeModelSerializer(serializers.ModelSerializer): for field_name, field in fields.fields.items(): if field.has_default(): - initials[field_name] = field.default + + value = field.default + + # Account for callable functions + if callable(value): + value = value() + + initials[field_name] = value return initials + def is_valid(self, raise_exception=False): + """ + Also override the is_valid() method, as in some cases get_initial() is not actually called. + """ + + # Calling super().is_valid creates self._validated_data + valid = super().is_valid(raise_exception) + + # Are we creating a new instance? + if self.instance is None: + ModelClass = self.Meta.model + + fields = model_meta.get_field_info(ModelClass) + + for field_name, field in fields.fields.items(): + + if field.has_default(): + if field not in self._validated_data: + + value = field.default + + # Account for callable functions + if callable(value): + value = value() + + self._validated_data[field_name] = value + + + return valid + def run_validation(self, data=empty): """ Perform serializer validation. In addition to running validators on the serializer fields, diff --git a/InvenTree/part/test_api.py b/InvenTree/part/test_api.py index 787c5d3f85..29df621914 100644 --- a/InvenTree/part/test_api.py +++ b/InvenTree/part/test_api.py @@ -13,6 +13,7 @@ from InvenTree.status_codes import StockStatus from part.models import Part, PartCategory from stock.models import StockItem from company.models import Company +from common.models import InvenTreeSetting class PartAPITest(InvenTreeAPITestCase): @@ -332,7 +333,38 @@ class PartAPITest(InvenTreeAPITestCase): # Check that the un-specified fields have used correct default values self.assertTrue(data['active']) self.assertFalse(data['virtual']) - self.assertTrue(data['purchaseable']) + + # By default, parts are not purchaseable + self.assertFalse(data['purchaseable']) + + # Set the default 'purchaseable' status to True + InvenTreeSetting.set_setting( + 'PART_PURCHASEABLE', + True, + self.user + ) + + response = self.client.post(url, { + 'name': 'all defaults', + 'description': 'my test part 2', + 'category': 1, + }) + + # Part should now be purchaseable by default + self.assertTrue(response.data['purchaseable']) + + # "default" values should not be used if the value is specified + response = self.client.post(url, { + 'name': 'all defaults', + 'description': 'my test part 2', + 'category': 1, + 'active': False, + 'purchaseable': False, + }) + + self.assertFalse(response.data['active']) + self.assertFalse(response.data['purchaseable']) + class PartDetailTests(InvenTreeAPITestCase):