Coverage for backend/django/Economics/formulas/models.py: 93%
56 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-07-22 05:22 +0000
« 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
4from core.managers import AccessControlManager, AllFlowsheetStatesManager
5from Economics.shared.model_base import FlowsheetScopedEconomicsModel
8class EconomicsMetricFormula(FlowsheetScopedEconomicsModel):
9 """Persist the formula envelope used to calculate one study financial metric."""
11 same_flowsheet_fields = ("study", "property_value")
13 flowsheet_state = models.ForeignKey(
14 "core_auxiliary.FlowsheetState",
15 on_delete=models.CASCADE,
16 related_name="economics_metric_formulas",
17 )
18 study = models.ForeignKey(
19 "EconomicsStudy",
20 on_delete=models.CASCADE,
21 related_name="metric_formulas",
22 )
23 property_value = models.ForeignKey(
24 "core_auxiliary.PropertyValue",
25 on_delete=models.SET_NULL,
26 related_name="economics_metric_formulas",
27 null=True,
28 blank=True,
29 )
30 metric_key = models.CharField(max_length=96)
31 formula_key = models.CharField(max_length=128)
32 formula = models.TextField(blank=True)
33 property_formula = models.TextField(blank=True)
34 unit = models.CharField(max_length=64, blank=True)
35 value = models.CharField(max_length=128, null=True, blank=True)
36 status = models.CharField(max_length=32, default="calculated")
37 formula_audit = models.JSONField(default=dict, blank=True)
38 blocked_reason = models.TextField(blank=True)
39 created_at = models.DateTimeField(auto_now_add=True)
40 updated_at = models.DateTimeField(auto_now=True)
42 objects = AccessControlManager()
43 all_states = AllFlowsheetStatesManager()
45 class Meta:
46 ordering = ["metric_key"]
47 constraints = [
48 models.UniqueConstraint(
49 fields=["study", "metric_key"],
50 name="unique_metric_formula_per_study",
51 ),
52 ]
54 def __str__(self):
55 return f"{self.study.name} {self.metric_key}"
57class EconomicsLineFormula(FlowsheetScopedEconomicsModel):
58 """Persist the formula envelope used to calculate one economics line property."""
60 same_flowsheet_fields = ("study", "property_value", "capital_line", "operating_line")
62 flowsheet_state = models.ForeignKey(
63 "core_auxiliary.FlowsheetState",
64 on_delete=models.CASCADE,
65 related_name="economics_line_formulas",
66 )
67 study = models.ForeignKey(
68 "EconomicsStudy",
69 on_delete=models.CASCADE,
70 related_name="line_formulas",
71 )
72 property_value = models.ForeignKey(
73 "core_auxiliary.PropertyValue",
74 on_delete=models.SET_NULL,
75 related_name="economics_line_formulas",
76 null=True,
77 blank=True,
78 )
79 capital_line = models.ForeignKey(
80 "CapitalCostLine",
81 on_delete=models.CASCADE,
82 related_name="formula_records",
83 null=True,
84 blank=True,
85 )
86 operating_line = models.ForeignKey(
87 "OperatingCostLine",
88 on_delete=models.CASCADE,
89 related_name="formula_records",
90 null=True,
91 blank=True,
92 )
93 line_key = models.CharField(max_length=128)
94 formula_key = models.CharField(max_length=128)
95 formula = models.TextField(blank=True)
96 property_formula = models.TextField(blank=True)
97 unit = models.CharField(max_length=64, blank=True)
98 value = models.CharField(max_length=128, null=True, blank=True)
99 status = models.CharField(max_length=32, default="calculated")
100 formula_audit = models.JSONField(default=dict, blank=True)
101 blocked_reason = models.TextField(blank=True)
102 created_at = models.DateTimeField(auto_now_add=True)
103 updated_at = models.DateTimeField(auto_now=True)
105 objects = AccessControlManager()
106 all_states = AllFlowsheetStatesManager()
108 class Meta:
109 ordering = ["line_key"]
110 constraints = [
111 models.UniqueConstraint(
112 fields=["study", "line_key"],
113 name="unique_line_formula_per_study",
114 ),
115 ]
117 def clean(self):
118 super().clean()
119 if bool(self.capital_line_id) == bool(self.operating_line_id): 119 ↛ 120line 119 didn't jump to line 120 because the condition on line 119 was never true
120 raise ValidationError({"line_key": "Line formula records must reference exactly one economics line."})
122 def __str__(self):
123 return f"{self.study.name} {self.line_key}"