from __future__ import annotations from datetime import datetime from typing import TYPE_CHECKING, List from .enums import MiningOperationType from sqlalchemy import DateTime, Enum as SQLEnum, ForeignKey, Integer, String, Text 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 from .pricing_settings import PricingSettings class Project(Base): """Top-level mining project grouping multiple scenarios.""" __tablename__ = "projects" id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True) name: Mapped[str] = mapped_column(String(255), nullable=False, unique=True) location: Mapped[str | None] = mapped_column(String(255), nullable=True) operation_type: Mapped[MiningOperationType] = mapped_column( SQLEnum(MiningOperationType, name="miningoperationtype", create_type=False), nullable=False, default=MiningOperationType.OTHER, ) description: Mapped[str | None] = mapped_column(Text, nullable=True) pricing_settings_id: Mapped[int | None] = mapped_column( ForeignKey("pricing_settings.id", ondelete="SET NULL"), 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() ) scenarios: Mapped[List["Scenario"]] = relationship( "Scenario", back_populates="project", cascade="all, delete-orphan", passive_deletes=True, ) pricing_settings: Mapped["PricingSettings | None"] = relationship( "PricingSettings", back_populates="projects", ) def __repr__(self) -> str: # pragma: no cover - helpful for debugging return f"Project(id={self.id!r}, name={self.name!r})"