Coverage for backend/django/Economics/results/models.py: 98%
101 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 django.db import models
3from core.managers import AccessControlManager
4from Economics.shared.choices import ResultDependencyType, ResultLineKind, ResultRunStatus
5from Economics.shared.model_base import FlowsheetScopedEconomicsModel
8class EconomicsResultRun(FlowsheetScopedEconomicsModel):
9 same_flowsheet_fields = ("study",)
11 flowsheet = models.ForeignKey("core_auxiliary.Flowsheet", on_delete=models.CASCADE, related_name="economics_result_runs")
12 study = models.ForeignKey("EconomicsStudy", on_delete=models.CASCADE, related_name="result_runs")
13 status = models.CharField(max_length=32, choices=ResultRunStatus.choices, default=ResultRunStatus.DRAFT)
14 result_currency = models.CharField(max_length=3, default="NZD")
15 result_basis_date = models.DateField(null=True, blank=True)
16 warning_payload = models.JSONField(default=dict, blank=True)
17 created_at = models.DateTimeField(auto_now_add=True)
18 completed_at = models.DateTimeField(null=True, blank=True)
20 objects = AccessControlManager()
22 class Meta:
23 ordering = ["-created_at"]
25 def __str__(self):
26 return f"{self.study.name} result run {self.pk or 'unsaved'}"
28class EconomicsResultDependency(FlowsheetScopedEconomicsModel):
29 same_flowsheet_fields = (
30 "result_run",
31 "source_assumptions",
32 "source_baseline",
33 "source_settings_profile",
34 "source_costable_item",
35 "source_cost_curve",
36 "source_capital_line",
37 "source_operating_line",
38 "source_scenario",
39 "source_property_info",
40 )
42 flowsheet = models.ForeignKey("core_auxiliary.Flowsheet", on_delete=models.CASCADE, related_name="economics_result_dependencies")
43 result_run = models.ForeignKey("EconomicsResultRun", on_delete=models.CASCADE, related_name="dependencies")
44 dependency_type = models.CharField(max_length=64, choices=ResultDependencyType.choices)
45 dependency_key = models.CharField(max_length=160)
46 fingerprint_value = models.CharField(max_length=160)
47 fingerprint_algorithm = models.CharField(max_length=32, default="sha256")
48 fingerprint_basis = models.CharField(max_length=128, blank=True)
49 source_label = models.CharField(max_length=160, blank=True)
50 source_row_key = models.CharField(max_length=160, blank=True)
51 source_version = models.CharField(max_length=128, blank=True)
52 source_assumptions = models.ForeignKey(
53 "EconomicsAssumptions",
54 on_delete=models.SET_NULL,
55 related_name="result_dependencies",
56 null=True,
57 blank=True,
58 )
59 source_baseline = models.ForeignKey(
60 "EconomicsBaseline",
61 on_delete=models.SET_NULL,
62 related_name="result_dependencies",
63 null=True,
64 blank=True,
65 )
66 source_settings_profile = models.ForeignKey(
67 "EconomicsSettingsProfile",
68 on_delete=models.SET_NULL,
69 related_name="result_dependencies",
70 null=True,
71 blank=True,
72 )
73 source_costable_item = models.ForeignKey(
74 "CostableItem",
75 on_delete=models.SET_NULL,
76 related_name="result_dependencies",
77 null=True,
78 blank=True,
79 )
80 source_cost_curve = models.ForeignKey(
81 "CostCurve",
82 on_delete=models.SET_NULL,
83 related_name="result_dependencies",
84 null=True,
85 blank=True,
86 )
87 source_capital_line = models.ForeignKey(
88 "CapitalCostLine",
89 on_delete=models.SET_NULL,
90 related_name="result_dependencies",
91 null=True,
92 blank=True,
93 )
94 source_operating_line = models.ForeignKey(
95 "OperatingCostLine",
96 on_delete=models.SET_NULL,
97 related_name="result_dependencies",
98 null=True,
99 blank=True,
100 )
101 source_index_series = models.ForeignKey(
102 "CostIndexSeries",
103 on_delete=models.SET_NULL,
104 related_name="result_dependencies",
105 null=True,
106 blank=True,
107 )
108 source_index_value = models.ForeignKey(
109 "CostIndexValue",
110 on_delete=models.SET_NULL,
111 related_name="result_dependencies",
112 null=True,
113 blank=True,
114 )
115 source_scenario = models.ForeignKey(
116 "core_auxiliary.Scenario",
117 on_delete=models.SET_NULL,
118 related_name="economics_result_dependencies",
119 null=True,
120 blank=True,
121 )
122 source_property_info = models.ForeignKey(
123 "core_auxiliary.PropertyInfo",
124 on_delete=models.SET_NULL,
125 related_name="economics_result_dependencies",
126 null=True,
127 blank=True,
128 )
129 created_at = models.DateTimeField(auto_now_add=True)
131 objects = AccessControlManager()
133 class Meta:
134 ordering = ["dependency_type", "dependency_key"]
135 constraints = [
136 models.UniqueConstraint(
137 fields=["result_run", "dependency_type", "dependency_key"],
138 name="unique_result_dependency_key_per_run",
139 ),
140 ]
142 def __str__(self):
143 return f"{self.dependency_type}:{self.dependency_key}"
145class EconomicsResultLine(FlowsheetScopedEconomicsModel):
146 same_flowsheet_fields = (
147 "result_run",
148 "source_costable_item",
149 "source_cost_curve",
150 "source_capital_line",
151 "source_operating_line",
152 "source_property_info",
153 )
155 flowsheet = models.ForeignKey("core_auxiliary.Flowsheet", on_delete=models.CASCADE, related_name="economics_result_lines")
156 result_run = models.ForeignKey("EconomicsResultRun", on_delete=models.CASCADE, related_name="lines")
157 kind = models.CharField(max_length=32, choices=ResultLineKind.choices)
158 group = models.CharField(max_length=64, blank=True)
159 label = models.CharField(max_length=160)
160 row_key = models.CharField(max_length=128)
161 amount = models.DecimalField(max_digits=18, decimal_places=4, null=True, blank=True)
162 unit = models.CharField(max_length=32, blank=True)
163 source_costable_item = models.ForeignKey(
164 "CostableItem",
165 on_delete=models.SET_NULL,
166 related_name="result_lines",
167 null=True,
168 blank=True,
169 )
170 source_cost_curve = models.ForeignKey(
171 "CostCurve",
172 on_delete=models.SET_NULL,
173 related_name="result_lines",
174 null=True,
175 blank=True,
176 )
177 source_capital_line = models.ForeignKey(
178 "CapitalCostLine",
179 on_delete=models.SET_NULL,
180 related_name="result_lines",
181 null=True,
182 blank=True,
183 )
184 source_operating_line = models.ForeignKey(
185 "OperatingCostLine",
186 on_delete=models.SET_NULL,
187 related_name="result_lines",
188 null=True,
189 blank=True,
190 )
191 source_index_value = models.ForeignKey(
192 "CostIndexValue",
193 on_delete=models.SET_NULL,
194 related_name="result_lines",
195 null=True,
196 blank=True,
197 )
198 source_property_info = models.ForeignKey(
199 "core_auxiliary.PropertyInfo",
200 on_delete=models.SET_NULL,
201 related_name="economics_result_lines",
202 null=True,
203 blank=True,
204 )
205 source_row_key = models.CharField(max_length=160, blank=True)
206 source_label = models.CharField(max_length=160, blank=True)
207 source_note = models.TextField(blank=True)
208 resource_source_kind = models.CharField(max_length=64, blank=True)
209 resource_source_object_name = models.CharField(max_length=160, blank=True)
210 resource_source_object_type = models.CharField(max_length=64, blank=True)
211 resource_property_name = models.CharField(max_length=160, blank=True)
212 resource_breakdown_category = models.CharField(max_length=64, blank=True)
213 annual_basis_quantity = models.DecimalField(max_digits=24, decimal_places=8, null=True, blank=True)
214 annual_basis_unit = models.CharField(max_length=32, blank=True)
215 warning_payload = models.JSONField(default=dict, blank=True)
216 sort_order = models.PositiveIntegerField(default=0)
217 created_at = models.DateTimeField(auto_now_add=True)
219 objects = AccessControlManager()
221 class Meta:
222 ordering = ["sort_order", "created_at"]
223 constraints = [
224 models.UniqueConstraint(
225 fields=["result_run", "row_key"],
226 name="unique_result_line_key_per_run",
227 ),
228 ]
230 def __str__(self):
231 return self.label
233class EconomicsChartDataset(FlowsheetScopedEconomicsModel):
234 same_flowsheet_fields = ("result_run",)
236 flowsheet = models.ForeignKey("core_auxiliary.Flowsheet", on_delete=models.CASCADE, related_name="economics_chart_datasets")
237 result_run = models.ForeignKey("EconomicsResultRun", on_delete=models.CASCADE, related_name="chart_datasets")
238 chart_key = models.CharField(max_length=128)
239 title = models.CharField(max_length=160)
240 chart_type = models.CharField(max_length=64)
241 source_row_keys = models.JSONField(default=list, blank=True)
242 chart_data = models.JSONField(default=dict, blank=True)
243 rendering_metadata = models.JSONField(default=dict, blank=True)
244 created_at = models.DateTimeField(auto_now_add=True)
246 objects = AccessControlManager()
248 class Meta:
249 ordering = ["created_at"]
250 constraints = [
251 models.UniqueConstraint(
252 fields=["result_run", "chart_key"],
253 name="unique_chart_dataset_key_per_run",
254 ),
255 ]
257 def __str__(self):
258 return self.title