Coverage for backend/django/Economics/shared/model_base.py: 98%

36 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2026-07-22 05:22 +0000

1from django.core.exceptions import ValidationError 

2from django.db import models 

3 

4from core.managers import AccessControlManager 

5 

6 

7def _validate_same_flowsheet_state(errors, field_name, value, flowsheet_state_id): 

8 if value is not None and value.flowsheet_state_id != flowsheet_state_id: 

9 errors[field_name] = "Referenced row must belong to the same flowsheet state." 

10 

11 

12class FlowsheetScopedEconomicsModel(models.Model): 

13 same_flowsheet_fields: tuple[str, ...] = () 

14 

15 class Meta: 

16 abstract = True 

17 

18 def clean(self): 

19 super().clean() 

20 errors = {} 

21 for field_name in self.same_flowsheet_fields: 

22 field_id_name = f"{field_name}_id" 

23 if getattr(self, field_id_name, None) is None: 

24 continue 

25 _validate_same_flowsheet_state( 

26 errors, 

27 field_name, 

28 getattr(self, field_name), 

29 self.flowsheet_state_id, 

30 ) 

31 if errors: 

32 raise ValidationError(errors) 

33 

34 def save(self, *args, **kwargs): 

35 self.full_clean() 

36 return super().save(*args, **kwargs) 

37 

38 

39class GlobalReferenceDataManager(AccessControlManager): 

40 """Access-control-compatible manager for global read-only reference data. 

41 

42 Project validation expects models to use ``AccessControlManager`` or 

43 ``SoftDeleteManager``. Stats NZ index rows are intentionally not 

44 flowsheet-owned, so this manager preserves that contract without filtering 

45 reads or pinning writes to a request flowsheet. These models are populated 

46 by developer-run management commands, not ordinary user APIs. 

47 """ 

48 

49 def create(self, **kwargs): 

50 return super(AccessControlManager, self).create(**kwargs) 

51 

52 def bulk_create(self, objs, **kwargs): 

53 return super(AccessControlManager, self).bulk_create(objs, **kwargs) 

54 

55 def get_queryset(self): 

56 return super(AccessControlManager, self).get_queryset() 

57 

58 

59class GlobalReferenceDataModel(models.Model): 

60 """Reference-data base that preserves model validation without flowsheet scoping.""" 

61 

62 class Meta: 

63 abstract = True 

64 

65 def save(self, *args, **kwargs): 

66 self.full_clean() 

67 return super().save(*args, **kwargs)