-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
118 lines (97 loc) · 3.99 KB
/
app.py
File metadata and controls
118 lines (97 loc) · 3.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# Flask Server
import os
from flask import Flask, request, jsonify
from werkzeug.utils import secure_filename # Helps clean messy filenames
from flask_cors import CORS
from models import db, JobProfile, Candidate
from parser_logic import parse_resume_text_only, parse_resume
app = Flask(__name__)
CORS(app) # Allows React app to talk to this server
# --- CONFIGURATION ---
# Tell Flask where to save the uploaded PDFs
UPLOAD_FOLDER = 'uploads'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
# Limit file size to 16MB (good practice)
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
# Connect to Supabase PostgreSQL database using SQLAlchemy
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('SQLALCHEMY_DATABASE_URI')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# Connect models.py to this app
db.init_app(app)
@app.route('/')
def home():
return jsonify({"status": "ok", "message": "Flask Server is Running!"})
# --- THE LOGIC BRIDGE (ROUTE) --
@app.route('/upload', methods=['POST'])
def upload_resumes():
try:
files = request.files.getlist('resumes')
skills_input = request.form.get('skills', '')
skills_list = [s.strip() for s in skills_input.split(',') if s.strip()]
min_experience = request.form.get('minExperience', 0)
try:
min_experience = float(min_experience)
except ValueError:
min_experience = 0.0
new_job = JobProfile(required_skills=skills_input)
db.session.add(new_job)
db.session.commit()
for file in files:
if file.filename == '': continue
filename = secure_filename(file.filename)
path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(path)
analysis, resume_text = parse_resume(path, skills_list, min_experience)
candidate = Candidate(
name=analysis.get('name'),
email=analysis.get('email'),
experience=analysis.get('experience_years', 0),
raw_text=resume_text,
extracted_skills=", ".join(analysis.get('found_skills', [])),
match_score=analysis.get('score'),
job_id=new_job.id
)
db.session.add(candidate)
db.session.commit()
return jsonify({"message": "Upload complete", "job_id": new_job.id})
except Exception as e:
db.session.rollback()
return jsonify({"error": str(e)}), 500
@app.route('/rank', methods=['POST'])
def rank_live():
try:
data = request.json
new_skills = data.get('skills', [])
min_exp_required = float(data.get('minExperience', 0))
candidates = Candidate.query.all()
results = []
for c in candidates:
analysis = parse_resume_text_only(c.raw_text, new_skills, min_exp_required)
results.append({
"id": c.id,
"name": c.name,
"score": analysis['score'],
"skills": analysis['found_skills'],
"experience": analysis.get('experience_years', 0)
})
return jsonify(sorted(results, key=lambda x: x['score'], reverse=True))
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/candidate/<int:candidate_id>', methods=['DELETE'])
def delete_candidate(candidate_id):
candidate = Candidate.query.get(candidate_id)
if candidate:
db.session.delete(candidate)
db.session.commit()
return jsonify({"message": f"Candidate {candidate_id} deleted"}), 200
return jsonify({"error": "Candidate not found"}), 404
if __name__ == '__main__':
with app.app_context():
try:
db.create_all()
print("Database Tables Ready.")
except Exception as e:
print(f"WARNING: Could not reach database at startup: {e}")
print("Flask will still start — restore your Supabase project if it is paused.")
app.run(debug=True, port=5000)