from __future__ import annotations from abc import ABC, abstractmethod from domain.modelling.plan import Plan class PlanRepository(ABC): """Persists a Plan (and its Plan Measures) for a Property + Scenario. One Plan per (Property, Scenario). The write is idempotent on re-run: it replaces the existing Plan for that pair rather than duplicating (ADR-0012 / ADR-0017). `portfolio_id` and `is_default` are supplied by the orchestrator (the former from the trigger, the latter from the Scenario). """ @abstractmethod def save( self, plan: Plan, *, property_id: int, scenario_id: int, portfolio_id: int, is_default: bool, ) -> int: """Persist ``plan`` and return its Plan id, replacing any existing Plan for ``(property_id, scenario_id)``.""" ...