feat: Implement initial capex calculation feature

- Added CapexComponentInput, CapexParameters, CapexCalculationRequest, CapexCalculationResult, and related schemas for capex calculations.
- Introduced calculate_initial_capex function to aggregate capex components and compute totals and timelines.
- Created ProjectCapexRepository and ScenarioCapexRepository for managing capex snapshots in the database.
- Developed capex.html template for capturing and displaying initial capex data.
- Registered common Jinja2 filters for formatting currency and percentages.
- Implemented unit and integration tests for capex calculation functionality.
- Updated unit of work to include new repositories for capex management.
This commit is contained in:
2025-11-12 23:51:52 +01:00
parent 6c1570a254
commit d9fd82b2e3
16 changed files with 1566 additions and 93 deletions

View File

@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING, List
from .enums import MiningOperationType, sql_enum
from .profitability_snapshot import ProjectProfitability
from .capex_snapshot import ProjectCapexSnapshot
from sqlalchemy import DateTime, ForeignKey, Integer, String, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship
@@ -59,6 +60,13 @@ class Project(Base):
order_by=lambda: ProjectProfitability.calculated_at.desc(),
passive_deletes=True,
)
capex_snapshots: Mapped[List["ProjectCapexSnapshot"]] = relationship(
"ProjectCapexSnapshot",
back_populates="project",
cascade="all, delete-orphan",
order_by=lambda: ProjectCapexSnapshot.calculated_at.desc(),
passive_deletes=True,
)
@property
def latest_profitability(self) -> "ProjectProfitability | None":
@@ -68,5 +76,13 @@ class Project(Base):
return None
return self.profitability_snapshots[0]
@property
def latest_capex(self) -> "ProjectCapexSnapshot | None":
"""Return the most recent capex snapshot, if any."""
if not self.capex_snapshots:
return None
return self.capex_snapshots[0]
def __repr__(self) -> str: # pragma: no cover - helpful for debugging
return f"Project(id={self.id!r}, name={self.name!r})"