- 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.
51 lines
1.4 KiB
Python
51 lines
1.4 KiB
Python
"""Domain-level exceptions for service and repository layers."""
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Sequence
|
|
|
|
|
|
class EntityNotFoundError(Exception):
|
|
"""Raised when a requested entity cannot be located."""
|
|
|
|
|
|
class EntityConflictError(Exception):
|
|
"""Raised when attempting to create or update an entity that violates uniqueness."""
|
|
|
|
|
|
class AuthorizationError(Exception):
|
|
"""Raised when a user lacks permission to perform an action."""
|
|
|
|
|
|
@dataclass(eq=False)
|
|
class ScenarioValidationError(Exception):
|
|
"""Raised when scenarios fail comparison validation rules."""
|
|
|
|
code: str
|
|
message: str
|
|
scenario_ids: Sequence[int] | None = None
|
|
|
|
def __str__(self) -> str: # pragma: no cover - mirrors message for logging
|
|
return self.message
|
|
|
|
|
|
@dataclass(eq=False)
|
|
class ProfitabilityValidationError(Exception):
|
|
"""Raised when profitability calculation inputs fail domain validation."""
|
|
|
|
message: str
|
|
field_errors: Sequence[str] | None = None
|
|
|
|
def __str__(self) -> str: # pragma: no cover - mirrors message for logging
|
|
return self.message
|
|
|
|
|
|
@dataclass(eq=False)
|
|
class CapexValidationError(Exception):
|
|
"""Raised when capex calculation inputs fail domain validation."""
|
|
|
|
message: str
|
|
field_errors: Sequence[str] | None = None
|
|
|
|
def __str__(self) -> str: # pragma: no cover - mirrors message for logging
|
|
return self.message
|