""" AssetStatus Model. This AssetStatus model uses sqlalchemy. It's used to store information about asset processing statuses """ import json from datetime import datetime from typing import Any from sqlalchemy import Column, DateTime, ForeignKey, Integer, String, Text from sqlalchemy.orm import Mapped from assets.connectors import mysql from assets.constants import error from assets.exceptions import AssetStatusNotFound class AssetStatus(mysql.AuModel): """Table definition for asset_status table.""" __tablename__ = "asset_status" asset_status_id: Mapped[int] = Column( "id", Integer, primary_key=True, autoincrement=True ) asset_upload_id: Mapped[int] = Column(Integer, ForeignKey("asset_upload.id")) status: Mapped[str] = Column(String(50), nullable=False) description: Mapped[str] = Column(String(512), nullable=True) message: Mapped[str] = Column(Text, nullable=True) status_time: Mapped[datetime] = Column(DateTime, nullable=False) def as_dict(self) -> dict[str, Any]: """Return object as dict. Returns: dict: Dictionary representation of object """ asset_status_dict = { "id": self.asset_status_id, "asset_upload_id": self.asset_upload_id, "status": self.status, "description": self.description, "status_time": self.status_time, "message": self.message and json.loads(self.message), } return asset_status_dict def create_asset_status( asset_upload_id: int, status: str, status_time: datetime, description: str | None = None, message: str | None = None, ) -> None: """Create new asset status item in the table. Args: asset_upload_id (int): Asset upload id. status (str): Asset status. description (str): Asset status description. message (str): Asset status message description. status_time (datetime.datetime): Asset status time. """ with mysql.au_db_session() as session: session.add( AssetStatus( asset_upload_id=asset_upload_id, status=status, description=description or "", message=message or "", status_time=status_time, ) ) def get_last_asset_status(asset_upload_id: int) -> dict[str, Any]: """Return last asset status by asset upload id. Args: asset_upload_id (int): Asset upload id. Returns: dict: Last asset status info """ filters = [(AssetStatus.asset_upload_id == asset_upload_id)] with mysql.au_db_session(read_only=True) as session: asset_status = ( session.query(AssetStatus) .filter(*filters) .order_by(AssetStatus.status_time.desc()) .first() ) if not asset_status: raise AssetStatusNotFound(error.ERROR_ASSET_STATUS_NOT_FOUND) return asset_status.as_dict() def get_asset_statuses_by_asset_upload_ids( asset_upload_ids: list[int], ) -> dict[int, dict[str, Any]]: """Return the list of asset statuses by asset upload id. Args: asset_upload_ids (list): List of asset_upload ids. Returns: dict: list of asset statuses. """ filters = [(AssetStatus.asset_upload_id.in_(asset_upload_ids))] with mysql.au_db_session(read_only=True) as session: asset_statuses = ( session.query(AssetStatus) .filter(*filters) .order_by(AssetStatus.status_time.desc()) .all() ) data: dict[int, list[dict[str, Any]]] = { asset_upload_id: [] for asset_upload_id in asset_upload_ids } for asset_status in asset_statuses: data[asset_status.asset_upload_id].append(asset_status.as_dict()) result = {} for asset_upload_id in asset_upload_ids: if data[asset_upload_id]: result[asset_upload_id] = data[asset_upload_id][0] else: result[asset_upload_id] = {} return result