import sqlite3 from datetime import datetime def get_database_connection(): """Create and return a database connection""" conn = sqlite3.connect('resume_data.db') return conn def init_database(): """Initialize database tables""" conn = get_database_connection() cursor = conn.cursor() # Create resume_data table cursor.execute(''' CREATE TABLE IF NOT EXISTS resume_data ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT NOT NULL, phone TEXT NOT NULL, linkedin TEXT, github TEXT, portfolio TEXT, summary TEXT, target_role TEXT, target_category TEXT, education TEXT, experience TEXT, projects TEXT, skills TEXT, template TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ''') # Create resume_skills table cursor.execute(''' CREATE TABLE IF NOT EXISTS resume_skills ( id INTEGER PRIMARY KEY AUTOINCREMENT, resume_id INTEGER, skill_name TEXT NOT NULL, skill_category TEXT NOT NULL, proficiency_score REAL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (resume_id) REFERENCES resume_data (id) ) ''') # Create resume_analysis table cursor.execute(''' CREATE TABLE IF NOT EXISTS resume_analysis ( id INTEGER PRIMARY KEY AUTOINCREMENT, resume_id INTEGER, ats_score REAL, keyword_match_score REAL, format_score REAL, section_score REAL, missing_skills TEXT, recommendations TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (resume_id) REFERENCES resume_data (id) ) ''') # Create admin_logs table cursor.execute(''' CREATE TABLE IF NOT EXISTS admin_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, admin_email TEXT NOT NULL, action TEXT NOT NULL, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ''') # Create admin table cursor.execute(''' CREATE TABLE IF NOT EXISTS admin ( id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT NOT NULL UNIQUE, password TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ''') conn.commit() conn.close() def save_resume_data(data): """Save resume data to database""" conn = get_database_connection() cursor = conn.cursor() try: personal_info = data.get('personal_info', {}) cursor.execute(''' INSERT INTO resume_data ( name, email, phone, linkedin, github, portfolio, summary, target_role, target_category, education, experience, projects, skills, template ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ''', ( personal_info.get('full_name', ''), personal_info.get('email', ''), personal_info.get('phone', ''), personal_info.get('linkedin', ''), personal_info.get('github', ''), personal_info.get('portfolio', ''), data.get('summary', ''), data.get('target_role', ''), data.get('target_category', ''), str(data.get('education', [])), str(data.get('experience', [])), str(data.get('projects', [])), str(data.get('skills', [])), data.get('template', '') )) conn.commit() return cursor.lastrowid except Exception as e: print(f"Error saving resume data: {str(e)}") conn.rollback() return None finally: conn.close() def save_analysis_data(resume_id, analysis): """Save resume analysis data""" conn = get_database_connection() cursor = conn.cursor() try: cursor.execute(''' INSERT INTO resume_analysis ( resume_id, ats_score, keyword_match_score, format_score, section_score, missing_skills, recommendations ) VALUES (?, ?, ?, ?, ?, ?, ?) ''', ( resume_id, float(analysis.get('ats_score', 0)), float(analysis.get('keyword_match_score', 0)), float(analysis.get('format_score', 0)), float(analysis.get('section_score', 0)), analysis.get('missing_skills', ''), analysis.get('recommendations', '') )) conn.commit() except Exception as e: print(f"Error saving analysis data: {str(e)}") conn.rollback() finally: conn.close() def get_resume_stats(): """Get statistics about resumes""" conn = get_database_connection() cursor = conn.cursor() try: # Get total resumes cursor.execute('SELECT COUNT(*) FROM resume_data') total_resumes = cursor.fetchone()[0] # Get average ATS score cursor.execute('SELECT AVG(ats_score) FROM resume_analysis') avg_ats_score = cursor.fetchone()[0] or 0 # Get recent activity cursor.execute(''' SELECT name, target_role, created_at FROM resume_data ORDER BY created_at DESC LIMIT 5 ''') recent_activity = cursor.fetchall() return { 'total_resumes': total_resumes, 'avg_ats_score': round(avg_ats_score, 2), 'recent_activity': recent_activity } except Exception as e: print(f"Error getting resume stats: {str(e)}") return None finally: conn.close() def log_admin_action(admin_email, action): """Log admin login/logout actions""" conn = get_database_connection() cursor = conn.cursor() try: cursor.execute(''' INSERT INTO admin_logs (admin_email, action) VALUES (?, ?) ''', (admin_email, action)) conn.commit() except Exception as e: print(f"Error logging admin action: {str(e)}") finally: conn.close() def get_admin_logs(): """Get all admin login/logout logs""" conn = get_database_connection() cursor = conn.cursor() try: cursor.execute(''' SELECT admin_email, action, timestamp FROM admin_logs ORDER BY timestamp DESC ''') return cursor.fetchall() except Exception as e: print(f"Error getting admin logs: {str(e)}") return [] finally: conn.close() def get_all_resume_data(): """Get all resume data for admin dashboard""" conn = get_database_connection() cursor = conn.cursor() try: # Get resume data joined with analysis data cursor.execute(''' SELECT r.id, r.name, r.email, r.phone, r.linkedin, r.github, r.portfolio, r.target_role, r.target_category, r.created_at, a.ats_score, a.keyword_match_score, a.format_score, a.section_score FROM resume_data r LEFT JOIN resume_analysis a ON r.id = a.resume_id ORDER BY r.created_at DESC ''') return cursor.fetchall() except Exception as e: print(f"Error getting resume data: {str(e)}") return [] finally: conn.close() def verify_admin(email, password): """Verify admin credentials""" conn = get_database_connection() cursor = conn.cursor() try: cursor.execute('SELECT * FROM admin WHERE email = ? AND password = ?', (email, password)) result = cursor.fetchone() return bool(result) except Exception as e: print(f"Error verifying admin: {str(e)}") return False finally: conn.close() def add_admin(email, password): """Add a new admin""" conn = get_database_connection() cursor = conn.cursor() try: cursor.execute('INSERT INTO admin (email, password) VALUES (?, ?)', (email, password)) conn.commit() return True except Exception as e: print(f"Error adding admin: {str(e)}") return False finally: conn.close() def save_ai_analysis_data(resume_id, analysis_data): """Save AI analysis data to the database""" conn = get_database_connection() cursor = conn.cursor() try: # Check if the ai_analysis table exists cursor.execute(""" CREATE TABLE IF NOT EXISTS ai_analysis ( id INTEGER PRIMARY KEY AUTOINCREMENT, resume_id INTEGER, model_used TEXT, resume_score INTEGER, job_role TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (resume_id) REFERENCES resume_data (id) ) """) # Insert the analysis data cursor.execute(""" INSERT INTO ai_analysis ( resume_id, model_used, resume_score, job_role ) VALUES (?, ?, ?, ?) """, ( resume_id, analysis_data.get('model_used', ''), analysis_data.get('resume_score', 0), analysis_data.get('job_role', '') )) conn.commit() return cursor.lastrowid except Exception as e: print(f"Error saving AI analysis data: {e}") conn.rollback() raise finally: conn.close() def get_ai_analysis_stats(): """Get statistics about AI analyzer usage""" conn = get_database_connection() cursor = conn.cursor() try: # Check if the ai_analysis table exists cursor.execute(""" SELECT name FROM sqlite_master WHERE type='table' AND name='ai_analysis' """) if not cursor.fetchone(): return { "total_analyses": 0, "model_usage": [], "average_score": 0, "top_job_roles": [] } # Get total number of analyses cursor.execute("SELECT COUNT(*) FROM ai_analysis") total_analyses = cursor.fetchone()[0] # Get model usage statistics cursor.execute(""" SELECT model_used, COUNT(*) as count FROM ai_analysis GROUP BY model_used ORDER BY count DESC """) model_usage = [{"model": row[0], "count": row[1]} for row in cursor.fetchall()] # Get average resume score cursor.execute("SELECT AVG(resume_score) FROM ai_analysis") average_score = cursor.fetchone()[0] or 0 # Get top job roles cursor.execute(""" SELECT job_role, COUNT(*) as count FROM ai_analysis GROUP BY job_role ORDER BY count DESC LIMIT 5 """) top_job_roles = [{"role": row[0], "count": row[1]} for row in cursor.fetchall()] return { "total_analyses": total_analyses, "model_usage": model_usage, "average_score": round(average_score, 1), "top_job_roles": top_job_roles } except Exception as e: print(f"Error getting AI analysis stats: {e}") return { "total_analyses": 0, "model_usage": [], "average_score": 0, "top_job_roles": [] } finally: conn.close() def get_detailed_ai_analysis_stats(): """Get detailed statistics about AI analyzer usage including daily trends""" conn = get_database_connection() cursor = conn.cursor() try: # Check if the ai_analysis table exists cursor.execute(""" SELECT name FROM sqlite_master WHERE type='table' AND name='ai_analysis' """) if not cursor.fetchone(): return { "total_analyses": 0, "model_usage": [], "average_score": 0, "top_job_roles": [], "daily_trend": [], "score_distribution": [], "recent_analyses": [] } # Get total number of analyses cursor.execute("SELECT COUNT(*) FROM ai_analysis") total_analyses = cursor.fetchone()[0] # Get model usage statistics cursor.execute(""" SELECT model_used, COUNT(*) as count FROM ai_analysis GROUP BY model_used ORDER BY count DESC """) model_usage = [{"model": row[0], "count": row[1]} for row in cursor.fetchall()] # Get average resume score cursor.execute("SELECT AVG(resume_score) FROM ai_analysis") average_score = cursor.fetchone()[0] or 0 # Get top job roles cursor.execute(""" SELECT job_role, COUNT(*) as count FROM ai_analysis GROUP BY job_role ORDER BY count DESC LIMIT 5 """) top_job_roles = [{"role": row[0], "count": row[1]} for row in cursor.fetchall()] # Get daily trend for the last 7 days cursor.execute(""" SELECT DATE(created_at) as date, COUNT(*) as count FROM ai_analysis WHERE created_at >= date('now', '-7 days') GROUP BY DATE(created_at) ORDER BY date """) daily_trend = [{"date": row[0], "count": row[1]} for row in cursor.fetchall()] # Get score distribution score_ranges = [ {"min": 0, "max": 20, "range": "0-20"}, {"min": 21, "max": 40, "range": "21-40"}, {"min": 41, "max": 60, "range": "41-60"}, {"min": 61, "max": 80, "range": "61-80"}, {"min": 81, "max": 100, "range": "81-100"} ] score_distribution = [] for range_info in score_ranges: cursor.execute(""" SELECT COUNT(*) FROM ai_analysis WHERE resume_score >= ? AND resume_score <= ? """, (range_info["min"], range_info["max"])) count = cursor.fetchone()[0] score_distribution.append({"range": range_info["range"], "count": count}) # Get recent analyses cursor.execute(""" SELECT model_used, resume_score, job_role, datetime(created_at) as date FROM ai_analysis ORDER BY created_at DESC LIMIT 5 """) recent_analyses = [ { "model": row[0], "score": row[1], "job_role": row[2], "date": row[3] } for row in cursor.fetchall() ] return { "total_analyses": total_analyses, "model_usage": model_usage, "average_score": round(average_score, 1), "top_job_roles": top_job_roles, "daily_trend": daily_trend, "score_distribution": score_distribution, "recent_analyses": recent_analyses } except Exception as e: print(f"Error getting detailed AI analysis stats: {e}") return { "total_analyses": 0, "model_usage": [], "average_score": 0, "top_job_roles": [], "daily_trend": [], "score_distribution": [], "recent_analyses": [] } finally: conn.close() def reset_ai_analysis_stats(): """Reset AI analysis statistics by truncating the ai_analysis table""" conn = get_database_connection() cursor = conn.cursor() try: # Check if the ai_analysis table exists cursor.execute(""" SELECT name FROM sqlite_master WHERE type='table' AND name='ai_analysis' """) if not cursor.fetchone(): return {"success": False, "message": "AI analysis table does not exist"} # Delete all records from the ai_analysis table cursor.execute("DELETE FROM ai_analysis") conn.commit() return {"success": True, "message": "AI analysis statistics have been reset successfully"} except Exception as e: conn.rollback() print(f"Error resetting AI analysis stats: {e}") return {"success": False, "message": f"Error resetting AI analysis statistics: {str(e)}"} finally: conn.close()