"""PodcastSeason Model. This model represents an PodcastSeason """ import sqlalchemy from sqlalchemy import ForeignKey from sqlalchemy.dialects.mysql import INTEGER from podcast.connectors import mysql from podcast.constants import error from podcast.models import episode as episode_model from podcast.utils import exc class PodcastSeason(mysql.BaseModel): """PodcastSeason model.""" __tablename__ = 'podcast_season' id = sqlalchemy.Column(INTEGER(unsigned=True), primary_key=True, autoincrement=True) # noqa podcast_id = sqlalchemy.Column( INTEGER(unsigned=True), ForeignKey('podcast.id'), nullable=False ) number = sqlalchemy.Column(sqlalchemy.Integer) name = sqlalchemy.Column(sqlalchemy.VARCHAR(255)) external_id = sqlalchemy.Column(sqlalchemy.VARCHAR(64)) def to_dict(self): """Return the object as dictionary.""" return dict( id=self.id, podcast_id=self.podcast_id, number=self.number, name=self.name, external_id=self.external_id ) def get_seasons_by_ids(ids): """Return seasons by ids. Args: ids (list): list of season ids Returns: dict: containing the seasons. """ with mysql.pod_db_session(read_only=True) as session: rows = session.query(PodcastSeason).filter( PodcastSeason.id.in_(ids) ).all() items = [row.to_dict() for row in rows] return {'items': items} def create_seasons(podcast_id, seasons, is_update, session=None): """Create new seasons.""" if session: return _create_seasons(podcast_id, seasons, is_update, session) with mysql.pod_db_session() as session: return _create_seasons(podcast_id, seasons, is_update, session) def _create_seasons(podcast_id, seasons, is_update, session): """Create new seasons. if is_update is True, update existing and if new then create seasons. Args: podcast_id (int): The unique identifier of the podcast seasons (dict): The seasons data from which to create the season. is_update (boolean): The boolean flag to update seasons or not. session (obj): The sql session object. Returns: dict: containing the list of created/updated seasons dicts. """ season_results = [] if is_update: season_results, new_seasons = _update_seasons(podcast_id, seasons, session) else: new_seasons = seasons for season in new_seasons: season['podcast_id'] = podcast_id season_model = PodcastSeason(**season) session.add(season_model) season_results.append(season_model) session.flush() return [season.to_dict() for season in season_results] def _update_seasons(podcast_id, seasons, session): """Update seasons by podcast id. Raise error if there are incorrect or missing active season numbers. Update the existing seasons which are also present in seasons request data. Delete seasons if no active episodes are using seasons missing in seasons request data. Args: podcast_id (int): The unique identifier of the podcast seasons (dict): The seasons data from which to update the season. session (obj): The sql session object. Returns: updated_season_results (list of dict): The updated seasons. new_seasons (list of dict):The new seasons which needs to be season. """ new_seasons = [] old_seasons = [] episodes = session.query(episode_model.Episode.season_id).filter( episode_model.Episode.podcast_id == podcast_id, episode_model.Episode.is_deleted.isnot(True) ).all() active_season_ids = {episode['season_id'] for episode in episodes if episode['season_id']} existing_seasons = session.query(PodcastSeason.id).filter(PodcastSeason.podcast_id == podcast_id).all() existing_season_ids = {seasons['id'] for seasons in existing_seasons} for season in seasons: season_id = season.get('id') if season_id: if season_id in existing_season_ids: old_seasons.append(season) else: raise exc.OwsError.bad_request(error.ERROR_INCORRECT_SEASONS) elif season_id is None: new_seasons.append(season) old_season_ids = {season['id'] for season in old_seasons} if not active_season_ids.issubset(old_season_ids): missing_season_ids = active_season_ids - old_season_ids raise exc.OwsError.bad_request(error.ERROR_SEASON_IDS.format(missing_season_ids)) query = session.query(PodcastSeason) for old_season in old_seasons: update_query = query.filter(PodcastSeason.id == old_season['id']) update_query.update(old_season) delete_season_ids = existing_season_ids - old_season_ids for season_id in delete_season_ids: query.filter(PodcastSeason.id == season_id).delete() updated_seasons = query.filter(PodcastSeason.id.in_(old_season_ids)).all() session.flush() return updated_seasons, new_seasons def get_seasons_status(ids): """Return seasons status. Args: ids (list): List of season ids Returns: List of objects containing {'season_id': 123, 'is_active': True}. """ items = [] with mysql.pod_db_session() as session: episodes = session.query(episode_model.Episode.season_id).filter( episode_model.Episode.season_id.in_(ids), episode_model.Episode.is_deleted.isnot(True) ).all() active_season_ids = {episode.season_id for episode in episodes} for season_id in ids: if season_id in active_season_ids: items.append({'season_id': season_id, 'is_active': True}) else: items.append({'season_id': season_id, 'is_active': False}) return {'items': items}