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
« 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
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
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)
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")
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)
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 }
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()
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 )
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
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
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
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
110class EnableCostingRequestSerializer(serializers.Serializer):
111 simulation_object = serializers.IntegerField()
114class DuplicateStudyRequestSerializer(serializers.Serializer):
115 name = serializers.CharField(required=False, allow_blank=True, default="")