from flask import request, current_app from utils import get_client_ip class Activity: def __init__(self, db_connection_method): self.execute = db_connection_method def log(self, person_id, action, entity_type=None, entity_id=None, details=None): """Records an action in the activity_log table.""" try: ip_address = get_client_ip() user_agent = request.user_agent.string if request else None sql = """ INSERT INTO activity_log (person_id, action, entity_type, entity_id, details, ip_address, user_agent) VALUES (%s, %s, %s, %s, %s, %s, %s) """ self.execute(sql, [person_id, action, entity_type, entity_id, details, ip_address, user_agent], commit=True) except Exception as e: # We don't want logging to break the main application flow current_app.logger.error(f"Error logging activity: {e}") def get_recent_logs(self, limit=50, offset=0, search_query=None): """Fetches recent activity logs with person names, supporting pagination and search.""" params = [limit, offset] search_clause = "" if search_query: # Add wildcard percentages for partial matching term = f"%{search_query}%" search_clause = """ WHERE p.name ILIKE %s OR al.action ILIKE %s OR al.entity_type ILIKE %s OR al.details ILIKE %s """ # Prepend search terms to params list (limit/offset must change position if we were using ? placeholders # but with %s list, order matters. Let's reconstruct consistent order). # Actually, LIMIT/OFFSET are at the end. Search params come before. params = [term, term, term, term, limit, offset] query = f""" SELECT al.id, al.person_id, p.name as person_name, al.action, al.entity_type, al.entity_id, al.details, al.ip_address, al.user_agent, al.timestamp FROM activity_log al LEFT JOIN person p ON al.person_id = p.person_id {search_clause} ORDER BY al.timestamp DESC LIMIT %s OFFSET %s """ return self.execute(query, params)