from __future__ import annotations """Service layer for primary track management operations.""" from typing import Iterable from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import Session from backend.app.models import CombinedTrackModel, TrackCreate, TrackModel, TrackUpdate from backend.app.repositories import CombinedTrackRepository, TrackRepository def list_tracks(session: Session) -> list[TrackModel]: repo = TrackRepository(session) tracks = repo.list_all() return [TrackModel.model_validate(track) for track in tracks] def get_track(session: Session, track_id: str) -> TrackModel | None: repo = TrackRepository(session) track = repo.get(track_id) if track is None: return None return TrackModel.model_validate(track) def create_track(session: Session, payload: TrackCreate) -> TrackModel: repo = TrackRepository(session) try: track = repo.create(payload) session.commit() except IntegrityError as exc: session.rollback() raise ValueError( "Track with the same station pair already exists") from exc return TrackModel.model_validate(track) def update_track(session: Session, track_id: str, payload: TrackUpdate) -> TrackModel | None: repo = TrackRepository(session) track = repo.get(track_id) if track is None: return None repo.update(track, payload) session.commit() return TrackModel.model_validate(track) def delete_track(session: Session, track_id: str, regenerate: bool = False) -> bool: repo = TrackRepository(session) track = repo.get(track_id) if track is None: return False start_station_id = str(track.start_station_id) end_station_id = str(track.end_station_id) session.delete(track) session.commit() if regenerate: regenerate_combined_tracks(session, [start_station_id, end_station_id]) return True def regenerate_combined_tracks(session: Session, station_ids: Iterable[str]) -> list[CombinedTrackModel]: combined_repo = CombinedTrackRepository(session) station_id_set = set(station_ids) if not station_id_set: return [] # Remove combined tracks touching these stations for combined in combined_repo.list_all(): if {str(combined.start_station_id), str(combined.end_station_id)} & station_id_set: session.delete(combined) session.commit() # Rebuild combined tracks between affected station pairs from backend.app.services.combined_tracks import create_combined_track regenerated: list[CombinedTrackModel] = [] station_list = list(station_id_set) for i in range(len(station_list)): for j in range(i + 1, len(station_list)): result = create_combined_track( session, station_list[i], station_list[j]) if result is not None: regenerated.append(result) return regenerated __all__ = [ "list_tracks", "get_track", "create_track", "update_track", "delete_track", "regenerate_combined_tracks", ]