feat: Add Processing Opex functionality

- Introduced OpexValidationError for handling validation errors in processing opex calculations.
- Implemented ProjectProcessingOpexRepository and ScenarioProcessingOpexRepository for managing project and scenario-level processing opex snapshots.
- Enhanced UnitOfWork to include repositories for processing opex.
- Updated sidebar navigation and scenario detail templates to include links to the new Processing Opex Planner.
- Created a new template for the Processing Opex Planner with form handling for input components and parameters.
- Developed integration tests for processing opex calculations, covering HTML and JSON flows, including validation for currency mismatches and unsupported frequencies.
- Added unit tests for the calculation logic, ensuring correct handling of various scenarios and edge cases.
This commit is contained in:
2025-11-13 09:26:57 +01:00
parent 1240b08740
commit 1feae7ff85
16 changed files with 1931 additions and 11 deletions

View File

@@ -14,10 +14,12 @@ from services.repositories import (
PricingSettingsSeedResult,
ProjectRepository,
ProjectProfitabilityRepository,
ProjectProcessingOpexRepository,
ProjectCapexRepository,
RoleRepository,
ScenarioRepository,
ScenarioProfitabilityRepository,
ScenarioProcessingOpexRepository,
ScenarioCapexRepository,
SimulationParameterRepository,
UserRepository,
@@ -42,8 +44,10 @@ class UnitOfWork(AbstractContextManager["UnitOfWork"]):
self.simulation_parameters: SimulationParameterRepository | None = None
self.project_profitability: ProjectProfitabilityRepository | None = None
self.project_capex: ProjectCapexRepository | None = None
self.project_processing_opex: ProjectProcessingOpexRepository | None = None
self.scenario_profitability: ScenarioProfitabilityRepository | None = None
self.scenario_capex: ScenarioCapexRepository | None = None
self.scenario_processing_opex: ScenarioProcessingOpexRepository | None = None
self.users: UserRepository | None = None
self.roles: RoleRepository | None = None
self.pricing_settings: PricingSettingsRepository | None = None
@@ -58,10 +62,14 @@ class UnitOfWork(AbstractContextManager["UnitOfWork"]):
self.project_profitability = ProjectProfitabilityRepository(
self.session)
self.project_capex = ProjectCapexRepository(self.session)
self.project_processing_opex = ProjectProcessingOpexRepository(
self.session)
self.scenario_profitability = ScenarioProfitabilityRepository(
self.session
)
self.scenario_capex = ScenarioCapexRepository(self.session)
self.scenario_processing_opex = ScenarioProcessingOpexRepository(
self.session)
self.users = UserRepository(self.session)
self.roles = RoleRepository(self.session)
self.pricing_settings = PricingSettingsRepository(self.session)
@@ -82,8 +90,10 @@ class UnitOfWork(AbstractContextManager["UnitOfWork"]):
self.simulation_parameters = None
self.project_profitability = None
self.project_capex = None
self.project_processing_opex = None
self.scenario_profitability = None
self.scenario_capex = None
self.scenario_processing_opex = None
self.users = None
self.roles = None
self.pricing_settings = None