Check whether plan with EPC goal is compliant (and change goal_value back to required)🟩

This commit is contained in:
Daniel Roth 2026-02-12 16:08:37 +00:00
parent 080000123f
commit bf0fce8ca5
4 changed files with 42 additions and 38 deletions

View file

@ -153,7 +153,7 @@ class ScenarioModel(Base):
)
housing_type: Mapped[str] = mapped_column(String, nullable=False)
goal: Mapped[PortfolioGoal] = mapped_column(Enum(PortfolioGoal), nullable=False)
goal_value: Mapped[Optional[str]] = mapped_column(String, nullable=False)
goal_value: Mapped[str] = mapped_column(String, nullable=False)
trigger_file_path: Mapped[str] = mapped_column(String, nullable=False)
already_installed_file_path: Mapped[Optional[str]] = mapped_column(String)
patches_file_path: Mapped[Optional[str]] = mapped_column(String)

View file

@ -6,6 +6,7 @@ from backend.app.db.models.portfolio import PortfolioGoal
from backend.app.db.models.recommendations import PlanModel
from backend.app.domain.classes.scenario import Scenario
from backend.app.domain.records.plan_record import PlanRecord
from backend.app.utils import sap_to_epc
class Plan:
@ -47,14 +48,22 @@ class Plan:
@property
def is_compliant(self) -> bool:
raise NotImplementedError
goal: PortfolioGoal = self.scenario.record.goal
goal_value: str = self.scenario.record.goal_value
match goal:
case PortfolioGoal.INCREASING_EPC:
return True
if self.record.post_epc_rating:
post_epc = self.record.post_epc_rating.value
elif self.record.post_sap_points:
post_epc = sap_to_epc(self.record.post_sap_points)
else:
return False
if post_epc <= goal_value:
return True
return False
case _:
raise NotImplementedError

View file

@ -11,6 +11,7 @@ class ScenarioRecord:
created_at: datetime
housing_type: str
goal: PortfolioGoal
goal_value: str
trigger_file_path: str
multi_plan: bool
is_default: bool
@ -20,7 +21,6 @@ class ScenarioRecord:
non_invasive_recommendations_file_path: Optional[str] = None
exclusions: Optional[str] = None
goal_value: Optional[str] = None
cost: Optional[float] = None
contingency: Optional[float] = None
funding: Optional[float] = None

View file

@ -1,4 +1,4 @@
from typing import Callable, Optional
from typing import Callable
import pytest
from datetime import datetime
@ -15,16 +15,27 @@ def created_at_datetime() -> datetime:
@pytest.fixture
def plan_factory(
created_at_datetime: datetime,
) -> Callable[[int, "Epc", "Scenario"], "Plan"]:
"""
Returns a factory function to create plans with different attributes and scenarios.
"""
def epc_c_scenario(created_at_datetime: datetime) -> "Scenario":
# arrange
scenario_record = ScenarioRecord(
name="EPC C",
created_at=created_at_datetime,
housing_type="",
goal=PortfolioGoal.INCREASING_EPC,
goal_value="C",
trigger_file_path="",
multi_plan=False,
is_default=False,
)
return Scenario(record=scenario_record, id=1)
def _create_plan(
post_sap_points: int, post_epc_rating: "Epc", scenario: "Scenario"
) -> "Plan":
@pytest.fixture
def plan_factory(
epc_c_scenario: "Scenario", created_at_datetime: datetime
) -> Callable[[int, "Epc"], "Plan"]:
# returns a function to create plans with different attributes
def _create_plan(post_sap_points: int, post_epc_rating: "Epc") -> "Plan":
plan_record = PlanRecord(
property_id=1,
portfolio_id=1,
@ -33,43 +44,27 @@ def plan_factory(
post_sap_points=post_sap_points,
post_epc_rating=post_epc_rating,
)
return Plan(record=plan_record, scenario=scenario, id=1)
return Plan(record=plan_record, scenario=epc_c_scenario, id=1)
return _create_plan
@pytest.mark.parametrize(
"scenario_name, goal_value, post_sap_points, post_epc_rating, expected_compliance",
"post_sap_points, post_epc_rating, expected_compliance",
[
("EPC C", "C", 75, Epc.C, True),
("EPC A", "A", 100, Epc.A, True),
("EPC D", "D", 60, Epc.D, False),
("Achieve EPC B", None, 100, Epc.A, True),
("Achieve EPC B", None, 60, Epc.D, False),
(75, Epc.C, True),
(100, Epc.A, True),
(60, Epc.D, False),
],
)
def test_scenario_goal_is_epc_c(
plan_factory: Callable[[int, "Epc", "Scenario"], "Plan"],
scenario_name: str,
goal_value: Optional[str],
plan_factory: Callable[[int, "Epc"], "Plan"],
post_sap_points: int,
post_epc_rating: "Epc",
expected_compliance: bool,
) -> None:
# arrange
scenario_record = ScenarioRecord(
name=scenario_name,
created_at=datetime.now(),
housing_type="",
goal=PortfolioGoal.INCREASING_EPC,
goal_value=goal_value,
trigger_file_path="",
multi_plan=False,
is_default=False,
)
scenario = Scenario(record=scenario_record, id=1)
plan = plan_factory(post_sap_points, post_epc_rating, scenario)
plan = plan_factory(post_sap_points, post_epc_rating)
# act
actual_compliance: bool = plan.is_compliant