feat: add initial database models and changelog for financial inputs and projects

This commit is contained in:
2025-11-09 16:50:14 +01:00
parent c6a0eb2588
commit 203a5d08f2
7 changed files with 282 additions and 30 deletions

View File

@@ -0,0 +1,69 @@
from __future__ import annotations
from datetime import datetime
from enum import Enum
from typing import TYPE_CHECKING
from sqlalchemy import (
JSON,
DateTime,
Enum as SQLEnum,
ForeignKey,
Integer,
Numeric,
String,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.sql import func
from config.database import Base
if TYPE_CHECKING: # pragma: no cover
from .scenario import Scenario
class DistributionType(str, Enum):
"""Supported stochastic distribution families for simulations."""
NORMAL = "normal"
TRIANGULAR = "triangular"
UNIFORM = "uniform"
LOGNORMAL = "lognormal"
CUSTOM = "custom"
class SimulationParameter(Base):
"""Probability distribution settings for scenario simulations."""
__tablename__ = "simulation_parameters"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
scenario_id: Mapped[int] = mapped_column(
ForeignKey("scenarios.id", ondelete="CASCADE"), nullable=False, index=True
)
name: Mapped[str] = mapped_column(String(255), nullable=False)
distribution: Mapped[DistributionType] = mapped_column(
SQLEnum(DistributionType), nullable=False
)
mean_value: Mapped[float | None] = mapped_column(Numeric(18, 4), nullable=True)
standard_deviation: Mapped[float | None] = mapped_column(Numeric(18, 4), nullable=True)
minimum_value: Mapped[float | None] = mapped_column(Numeric(18, 4), nullable=True)
maximum_value: Mapped[float | None] = mapped_column(Numeric(18, 4), nullable=True)
unit: Mapped[str | None] = mapped_column(String(32), nullable=True)
metadata: Mapped[dict | None] = mapped_column(JSON, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), nullable=False, server_default=func.now()
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), nullable=False, server_default=func.now(), onupdate=func.now()
)
scenario: Mapped["Scenario"] = relationship(
"Scenario", back_populates="simulation_parameters"
)
def __repr__(self) -> str: # pragma: no cover
return (
f"SimulationParameter(id={self.id!r}, scenario_id={self.scenario_id!r}, "
f"name={self.name!r})"
)