from datetime import datetime from sqlalchemy import Select, func, select from sqlalchemy.orm import Session from app.models.audit import AuditLog class AuditRepository: @staticmethod def create( db: Session, *, actor_user_id: int | None, actor_username: str, action: str, entity_type: str, entity_id: int | None, entity_label: str, ip_address: str, user_agent: str, before_data: dict | list | None = None, after_data: dict | list | None = None, metadata: dict | list | None = None, ) -> AuditLog: audit_log = AuditLog( actor_user_id=actor_user_id, actor_username=actor_username, action=action, entity_type=entity_type, entity_id=entity_id, entity_label=entity_label, ip_address=ip_address, user_agent=user_agent, before_data=before_data, after_data=after_data, metadata_data=metadata, ) db.add(audit_log) db.commit() db.refresh(audit_log) return audit_log @staticmethod def query( *, entity_type: str | None = None, actor_user_id: int | None = None, action: str | None = None, date_from: datetime | None = None, date_to: datetime | None = None, ) -> Select[tuple[AuditLog]]: query = select(AuditLog) if entity_type: query = query.where(AuditLog.entity_type == entity_type) if actor_user_id is not None: query = query.where(AuditLog.actor_user_id == actor_user_id) if action: query = query.where(AuditLog.action == action) if date_from: query = query.where(AuditLog.created_at >= date_from) if date_to: query = query.where(AuditLog.created_at <= date_to) return query @staticmethod def list( db: Session, *, page: int, page_size: int, entity_type: str | None = None, actor_user_id: int | None = None, action: str | None = None, date_from: datetime | None = None, date_to: datetime | None = None, ) -> tuple[list[AuditLog], int]: base_query = AuditRepository.query( entity_type=entity_type, actor_user_id=actor_user_id, action=action, date_from=date_from, date_to=date_to, ) total = db.scalar(select(func.count()).select_from(base_query.subquery())) or 0 items = list( db.scalars( base_query .order_by(AuditLog.created_at.desc()) .offset((page - 1) * page_size) .limit(page_size) ) ) return items, total @staticmethod def latest(db: Session, limit: int = 10) -> list[AuditLog]: return list( db.scalars( select(AuditLog) .order_by(AuditLog.created_at.desc()) .limit(limit) ) )