""" Audit Log Router """ from typing import List, Optional from datetime import date from fastapi import APIRouter, Depends, Query, HTTPException from sqlalchemy.orm import Session from sqlalchemy import or_, desc, distinct from core.database import get_core_db from core.security import get_current_user # Assuming this exists from .models import AuditLog from .schemas import AuditLogListResponse, AuditLogResponse, AuditLogDetailResponse router = APIRouter() @router.get("/bitacora", response_model=AuditLogListResponse) async def get_bitacora( page: int = Query(1, ge=1), page_size: int = Query(50, ge=1, le=100), search: Optional[str] = None, username: Optional[str] = None, procedure: Optional[str] = None, reference: Optional[str] = None, date_from: Optional[date] = None, date_to: Optional[date] = None, db: Session = Depends(get_core_db) ): """ Get legacy audit log (Bitácora) """ query = db.query(AuditLog) # Filters if date_from: query = query.filter(AuditLog.date >= date_from) if date_to: query = query.filter(AuditLog.date <= date_to) if username: query = query.filter(AuditLog.username.ilike(f"%{username}%")) if procedure: # Exact match for dropdown filter usually better, but let's allow partial if manual # Legacy UI sends exact strings usually query = query.filter(AuditLog.procedure == procedure) if reference: query = query.filter(AuditLog.reference.ilike(f"%{reference}%")) if search: # General search across main columns search_filter = or_( AuditLog.reference.ilike(f"%{search}%"), AuditLog.procedure.ilike(f"%{search}%"), AuditLog.movement.ilike(f"%{search}%"), AuditLog.username.ilike(f"%{search}%") ) query = query.filter(search_filter) total = query.count() # Sort by ID desc (newest first) -> Legacy usually shows newest first or spec_id desc logs = query.order_by(desc(AuditLog.spec_id))\ .offset((page - 1) * page_size)\ .limit(page_size)\ .all() return { "data": logs, "total": total, "page": page, "page_size": page_size } @router.get("/bitacora/procedimientos", response_model=List[str]) async def get_procedures(db: Session = Depends(get_core_db)): """ Get distinct list of procedures for filters """ results = db.query(distinct(AuditLog.procedure))\ .order_by(AuditLog.procedure)\ .all() # verify if result is tuple return [r[0] for r in results if r[0]] @router.get("/bitacora/{spec_id}/detalle", response_model=AuditLogDetailResponse) async def get_audit_detail(spec_id: int, db: Session = Depends(get_core_db)): """ Get full detail of a log entry """ log = db.query(AuditLog).filter(AuditLog.spec_id == spec_id).first() if not log: raise HTTPException(status_code=404, detail="Log entry not found") return log