65 lines
2.2 KiB
Python
65 lines
2.2 KiB
Python
# Procyon — shared pipeline. One prepare path for both the web UI and the autopilot.
|
|
|
|
import os
|
|
|
|
import db
|
|
import tailor
|
|
import audit
|
|
import scraper
|
|
import resume_pdf
|
|
|
|
BASE = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
|
|
def prepare(job):
|
|
"""Score -> tailor -> draft -> PDF -> self-audit. Returns app_id. NO sending."""
|
|
score, opinion = tailor.score_job(job)
|
|
db.update_job_score(job['id'], score, opinion)
|
|
|
|
tracks, _master = tailor.build_master(job)
|
|
structured = tailor.structured_resume(job)
|
|
text = tailor.structured_to_text(structured)
|
|
subject = tailor.make_subject(job)
|
|
research = scraper.research_company(job)
|
|
body = tailor.draft_email(job, text, research=research)
|
|
|
|
# scrape a contact email (best-effort, for auto-send on approve) — only runs for
|
|
# the handful of jobs that get prepared, not the bulk discover.
|
|
if not (job.get('contact_email') or '').strip():
|
|
try:
|
|
contact = scraper.scrape_contact_email(job)
|
|
if contact:
|
|
db.set_job_contact_email(job['id'], contact)
|
|
except Exception:
|
|
pass
|
|
|
|
aid = db.create_application(job['id'], subject=subject, body=body)
|
|
|
|
# one-page PDF
|
|
pdf = ''
|
|
try:
|
|
out = os.path.join(BASE, 'data', 'resumes', f'app_{aid}.pdf')
|
|
os.makedirs(os.path.dirname(out), exist_ok=True)
|
|
resume_pdf.render(structured, out_path=out)
|
|
if os.path.exists(out):
|
|
pdf = out
|
|
except Exception as e:
|
|
print(f'pdf render failed: {e}')
|
|
|
|
# text version for display
|
|
rdir = os.path.join(BASE, 'data', 'tailored')
|
|
os.makedirs(rdir, exist_ok=True)
|
|
tpath = os.path.join(rdir, f'app_{aid}_resume.txt')
|
|
with open(tpath, 'w', encoding='utf-8') as f:
|
|
f.write(text)
|
|
|
|
db.update_application(aid, resume_path=tpath, tailored_pdf=pdf, status='tailored',
|
|
notes=f'tracks: {",".join(tracks)}')
|
|
|
|
# self-audit (now includes ATS keyword coverage)
|
|
checks = audit.run_audit(aid, job, subject, body, text)
|
|
ok = audit.all_pass(checks)
|
|
db.update_application(aid, status='audited', audit_json=str(checks))
|
|
db.set_job_status(job['id'], 'audited')
|
|
return aid
|