refactor(modelling): move PortfolioGoal to domain/modelling/

PortfolioGoal is domain vocabulary (a Scenario's goal — legacy planning branches
on PortfolioGoal.INCREASING_EPC), so it belongs in domain/ co-located with
scenario.py, mirroring how domain/epc/wall_type.py holds an enum that
infrastructure/ imports. This lets the consolidated ScenarioModel (next slice)
source the goal enum from domain without an infra→backend dependency.
portfolio.py keeps a re-export so every existing
`from ...portfolio import PortfolioGoal` caller is unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-06-03 22:44:48 +00:00
parent 01c2c3910e
commit 2fbd7147b7
2 changed files with 28 additions and 8 deletions

View file

@ -18,6 +18,11 @@ from backend.app.db.models.users import UserModel # noqa
from backend.app.db.models.materials import MaterialType
from datatypes.epc.domain.epc import Epc
# PortfolioGoal moved to the domain layer (ADR-0017 amendment). Re-exported here
# so the existing `from backend.app.db.models.portfolio import PortfolioGoal`
# callers keep working.
from domain.modelling.portfolio_goal import PortfolioGoal # noqa: F401
class PortfolioStatus(enum.Enum):
SCOPING = "scoping"
@ -32,14 +37,6 @@ class PortfolioStatus(enum.Enum):
NEEDS_REVIEW = "needs review"
class PortfolioGoal(enum.Enum): # TODO: Move to domain?
VALUATION_IMPROVEMENT = "Valuation Improvement"
INCREASING_EPC = "Increasing EPC"
REDUCING_CO2_EMISSIONS = "Reducing CO2 emissions"
ENERGY_SAVINGS = "Energy Savings"
NONE = "None"
class Portfolio(Base):
__tablename__ = "portfolio"
id = Column(Integer, primary_key=True, autoincrement=True)

View file

@ -0,0 +1,23 @@
"""PortfolioGoal — the retrofit objective a Scenario is scored against.
Domain vocabulary (ubiquitous language): the goal a user sets for a Scenario
raise the EPC band, cut CO₂, cut energy, or improve valuation. The enum
*values* are the canonical strings stored in the live ``scenario.goal`` /
``portfolio.goal`` columns and used by the front end; the Modelling stage's
Optimiser branches on them (#1160).
Lives in ``domain/`` (not ``backend/``) so the domain, persistence
(``infrastructure/postgres/modelling``) and legacy app layers share one
definition co-located with ``scenario.py``, which carries the goal. See
CONTEXT.md.
"""
import enum
class PortfolioGoal(enum.Enum):
VALUATION_IMPROVEMENT = "Valuation Improvement"
INCREASING_EPC = "Increasing EPC"
REDUCING_CO2_EMISSIONS = "Reducing CO2 emissions"
ENERGY_SAVINGS = "Energy Savings"
NONE = "None"