from __future__ import annotations from dataclasses import dataclass from datetime import date, datetime from typing import Iterable from models import MiningOperationType, ResourceType, ScenarioStatus def _normalise_lower_strings(values: Iterable[str]) -> tuple[str, ...]: unique: set[str] = set() for value in values: if not value: continue trimmed = value.strip().lower() if not trimmed: continue unique.add(trimmed) return tuple(sorted(unique)) def _normalise_upper_strings(values: Iterable[str]) -> tuple[str, ...]: unique: set[str] = set() for value in values: if not value: continue trimmed = value.strip().upper() if not trimmed: continue unique.add(trimmed) return tuple(sorted(unique)) @dataclass(slots=True, frozen=True) class ProjectExportFilters: """Filter parameters for project export queries.""" ids: tuple[int, ...] = () names: tuple[str, ...] = () name_contains: str | None = None locations: tuple[str, ...] = () operation_types: tuple[MiningOperationType, ...] = () created_from: datetime | None = None created_to: datetime | None = None updated_from: datetime | None = None updated_to: datetime | None = None def normalised_ids(self) -> tuple[int, ...]: unique = {identifier for identifier in self.ids if identifier > 0} return tuple(sorted(unique)) def normalised_names(self) -> tuple[str, ...]: return _normalise_lower_strings(self.names) def normalised_locations(self) -> tuple[str, ...]: return _normalise_lower_strings(self.locations) def name_search_pattern(self) -> str | None: if not self.name_contains: return None pattern = self.name_contains.strip() if not pattern: return None return f"%{pattern}%" @dataclass(slots=True, frozen=True) class ScenarioExportFilters: """Filter parameters for scenario export queries.""" ids: tuple[int, ...] = () project_ids: tuple[int, ...] = () project_names: tuple[str, ...] = () name_contains: str | None = None statuses: tuple[ScenarioStatus, ...] = () start_date_from: date | None = None start_date_to: date | None = None end_date_from: date | None = None end_date_to: date | None = None created_from: datetime | None = None created_to: datetime | None = None updated_from: datetime | None = None updated_to: datetime | None = None currencies: tuple[str, ...] = () primary_resources: tuple[ResourceType, ...] = () def normalised_ids(self) -> tuple[int, ...]: unique = {identifier for identifier in self.ids if identifier > 0} return tuple(sorted(unique)) def normalised_project_ids(self) -> tuple[int, ...]: unique = {identifier for identifier in self.project_ids if identifier > 0} return tuple(sorted(unique)) def normalised_project_names(self) -> tuple[str, ...]: return _normalise_lower_strings(self.project_names) def name_search_pattern(self) -> str | None: if not self.name_contains: return None pattern = self.name_contains.strip() if not pattern: return None return f"%{pattern}%" def normalised_currencies(self) -> tuple[str, ...]: return _normalise_upper_strings(self.currencies) __all__ = ( "ProjectExportFilters", "ScenarioExportFilters", )