Coverage for backend/django/Economics/studies/serializers.py: 85%

67 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2026-06-23 21:51 +0000

1from drf_spectacular.utils import extend_schema_field 

2from rest_framework import serializers 

3 

4from Economics.costing.capital.serializers import CapitalCostLineSerializer 

5from Economics.costing.costable_items.serializers import CostableItemSerializer 

6from Economics.costing.operating.serializers import OperatingCostLineSerializer 

7from Economics.results.serializers import EconomicsResultRunSerializer, ResultStatePayloadSerializer, _warning_summaries 

8from Economics.settings_profiles.serializers import EconomicsSettingsProfileSerializer 

9from Economics.shared.serializer_base import FlowsheetScopedSerializer 

10from Economics.studies.models import EconomicsStudy 

11from Economics.results.services.lifecycle.runs import classify_result_run 

12from Economics.settings_profiles.services.settings_profiles import get_or_create_default_settings_profile 

13 

14 

15class EconomicsStudySerializer(FlowsheetScopedSerializer): 

16 same_flowsheet_fields = ("settings_profile",) 

17 result_state = serializers.SerializerMethodField() 

18 settings_profile_name = serializers.CharField(source="settings_profile.name", read_only=True) 

19 

20 class Meta: 

21 model = EconomicsStudy 

22 fields = ( 

23 "id", 

24 "flowsheet", 

25 "settings_profile", 

26 "settings_profile_name", 

27 "name", 

28 "description", 

29 "result_state", 

30 "created_at", 

31 "updated_at", 

32 ) 

33 read_only_fields = ("id", "flowsheet", "settings_profile_name", "result_state", "created_at", "updated_at") 

34 

35 def create(self, validated_data): 

36 if validated_data.get("settings_profile") is None: 36 ↛ 37line 36 didn't jump to line 37 because the condition on line 36 was never true

37 flowsheet = validated_data.get("flowsheet") 

38 if flowsheet is not None: 

39 validated_data["settings_profile"] = get_or_create_default_settings_profile(flowsheet) 

40 return super().create(validated_data) 

41 

42 @extend_schema_field(ResultStatePayloadSerializer) 

43 def get_result_state(self, obj: EconomicsStudy) -> dict: 

44 run = obj.result_runs.order_by("-created_at", "-pk").first() 

45 if run is None: 

46 return { 

47 "run_id": None, 

48 "status": "not_calculated", 

49 "classification": "missing", 

50 "warnings": [], 

51 "requires_solve": False, 

52 } 

53 payload = run.warning_payload or {} 

54 return { 

55 "run_id": run.pk, 

56 "status": run.status, 

57 "classification": classify_result_run(run), 

58 "completed_at": run.completed_at, 

59 "warnings": _warning_summaries(payload), 

60 "requires_solve": bool(payload.get("requires_solve", False)), 

61 "latest_stale_reason": payload.get("latest_stale_reason", ""), 

62 } 

63 

64 

65class EconomicsStudyFullSerializer(EconomicsStudySerializer): 

66 assumptions = serializers.SerializerMethodField() 

67 baseline = serializers.SerializerMethodField() 

68 settings_profile_detail = serializers.SerializerMethodField() 

69 costable_items = CostableItemSerializer(many=True, read_only=True) 

70 capital_lines = CapitalCostLineSerializer(many=True, read_only=True) 

71 operating_lines = OperatingCostLineSerializer(many=True, read_only=True) 

72 current_result = serializers.SerializerMethodField() 

73 

74 class Meta(EconomicsStudySerializer.Meta): 

75 fields = EconomicsStudySerializer.Meta.fields + ( 

76 "settings_profile_detail", 

77 "assumptions", 

78 "baseline", 

79 "costable_items", 

80 "capital_lines", 

81 "operating_lines", 

82 "current_result", 

83 ) 

84 

85 @extend_schema_field(EconomicsSettingsProfileSerializer(allow_null=True)) 

86 def get_settings_profile_detail(self, obj: EconomicsStudy) -> dict | None: 

87 if obj.settings_profile_id is None: 87 ↛ 88line 87 didn't jump to line 88 because the condition on line 87 was never true

88 return None 

89 return EconomicsSettingsProfileSerializer(obj.settings_profile, context=self.context).data 

90 

91 @extend_schema_field(EconomicsSettingsProfileSerializer(allow_null=True)) 

92 def get_assumptions(self, obj: EconomicsStudy) -> dict | None: 

93 if obj.settings_profile_id is None: 93 ↛ 94line 93 didn't jump to line 94 because the condition on line 93 was never true

94 return None 

95 return EconomicsSettingsProfileSerializer(obj.settings_profile, context=self.context).data 

96 

97 @extend_schema_field(EconomicsSettingsProfileSerializer(allow_null=True)) 

98 def get_baseline(self, obj: EconomicsStudy) -> dict | None: 

99 if obj.settings_profile_id is None: 99 ↛ 100line 99 didn't jump to line 100 because the condition on line 99 was never true

100 return None 

101 return EconomicsSettingsProfileSerializer(obj.settings_profile, context=self.context).data 

102 

103 @extend_schema_field(EconomicsResultRunSerializer(allow_null=True)) 

104 def get_current_result(self, obj: EconomicsStudy) -> dict | None: 

105 run = obj.result_runs.filter(status="current").order_by("-created_at", "-pk").first() 

106 if run is None: 

107 return None 

108 return EconomicsResultRunSerializer(run, context=self.context).data 

109 

110class EnableCostingRequestSerializer(serializers.Serializer): 

111 simulation_object = serializers.IntegerField() 

112 

113 

114class DuplicateStudyRequestSerializer(serializers.Serializer): 

115 name = serializers.CharField(required=False, allow_blank=True, default="")