feat: ship premium IT-focused vacancy radar
deploy / deploy (push) Canceled after 0s

This commit is contained in:
Jens
2026-07-22 15:16:15 +02:00
parent 7d3d026d1d
commit 029df89265
23 changed files with 838 additions and 53 deletions
+12
View File
@@ -14,6 +14,7 @@ from apps.jobs.services.geocoding import resolve_cached_location
from apps.profiles.models import SearchProfile
from .normalization import normalize_token
from .relevance import assess_it_relevance, profile_requires_it_focus
@dataclass(frozen=True)
@@ -227,6 +228,9 @@ def _hard_exclusions(
conflicts = sorted(excluded_skills.intersection(explicit_job_skills))
if conflicts:
reasons.append("Uitgesloten verplichte skill: " + ", ".join(conflicts))
it_relevance = assess_it_relevance(job.original_title)
if profile_requires_it_focus(profile) and not it_relevance.relevant:
reasons.append(it_relevance.reason)
return reasons, distance.distance_confidence
@@ -292,6 +296,7 @@ def _analyze_with_ai(job: JobPosting, profile: SearchProfile) -> tuple[AiAnalysi
def calculate_score(job: JobPosting, profile: SearchProfile) -> ScoreResult:
distance = _distance(job, profile)
exclusions, distance_confidence = _hard_exclusions(job, profile, distance)
it_relevance = assess_it_relevance(job.original_title)
title_fit = _title_fit(job, profile)
skill_fit, present_skills, missing_skills = _skill_fit(job, profile)
features = job.analysis_features or {}
@@ -381,6 +386,8 @@ def calculate_score(job: JobPosting, profile: SearchProfile) -> ScoreResult:
concerns: list[str] = []
if title_fit >= 0.75:
positives.append("Functietitel sluit goed aan op het zoekprofiel.")
if it_relevance.relevant:
positives.append("IT-focus bevestigd via de functietitel.")
if present_skills:
positives.append("Herkenbare skills: " + ", ".join(present_skills[:6]))
if job.direct_employer and not job.recruiter:
@@ -435,6 +442,11 @@ def calculate_score(job: JobPosting, profile: SearchProfile) -> ScoreResult:
concerns=concerns,
hard_exclusions=exclusions,
evidence={
"it_relevance": {
"relevant": it_relevance.relevant,
"signals": list(it_relevance.signals),
"reason": it_relevance.reason,
},
"distance_km": distance.exact_distance_km,
"distance_has_data": distance.has_distance_data,
"distance_exact": distance.exact_distance_km is not None,