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
+29 -9
View File
@@ -4,13 +4,15 @@ from django.conf import settings
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.views import LoginView
from django.db.models import Count, Q
from django.db.models import Count, OuterRef, Q, Subquery
from django.http import JsonResponse
from django.utils import timezone
from django.views.generic import TemplateView
from apps.core.rate_limit import clear_rate_limit, is_rate_limited, register_rate_limit_failure
from apps.jobs.models import Application, JobPosting, ScoreRun
from apps.jobs.services.relevance import it_relevance_query
from apps.profiles.models import SearchProfile
from apps.sources.models import Source
from apps.sources.services.health import collect_source_health
@@ -83,9 +85,24 @@ class TodayView(LoginRequiredMixin, TemplateView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
profile = SearchProfile.objects.filter(user=self.request.user, is_active=True).first()
latest_score_id = (
ScoreRun.objects.filter(job_id=OuterRef("job_id"), profile=profile)
.order_by("-created_at")
.values("pk")[:1]
)
latest_scores = (
ScoreRun.objects.select_related("job", "job__employer", "profile")
.filter(job__status=JobPosting.Status.ACTIVE, hard_exclusions=[])
.filter(
profile=profile,
job__status=JobPosting.Status.ACTIVE,
hard_exclusions=[],
recommendation__in=[
ScoreRun.Recommendation.STRONG,
ScoreRun.Recommendation.POSSIBLE,
],
)
.filter(it_relevance_query("job__"), pk=Subquery(latest_score_id))
.order_by("-score", "-created_at")
)
# Eén score per vacature, zonder PostgreSQL-specifieke DISTINCT ON.
@@ -99,6 +116,10 @@ class TodayView(LoginRequiredMixin, TemplateView):
cards.append(score)
if len(cards) >= 20:
break
active_it_jobs = JobPosting.objects.filter(
Q(status=JobPosting.Status.ACTIVE) & it_relevance_query()
)
all_active_jobs = JobPosting.objects.filter(status=JobPosting.Status.ACTIVE)
context.update(
{
"score_cards": cards,
@@ -106,13 +127,12 @@ class TodayView(LoginRequiredMixin, TemplateView):
.exclude(status__in=[Application.Status.REJECTED, Application.Status.WITHDRAWN])
.select_related("job", "job__employer")
.order_by("follow_up_date", "-updated_at")[:3],
"active_jobs": JobPosting.objects.filter(status=JobPosting.Status.ACTIVE).count(),
"new_today": JobPosting.objects.filter(
first_seen__date=timezone.localdate()
).count(),
"applications_open": Application.objects.exclude(
status__in=[Application.Status.REJECTED, Application.Status.WITHDRAWN]
).count(),
"active_jobs": active_it_jobs.count(),
"filtered_non_it_jobs": all_active_jobs.exclude(it_relevance_query()).count(),
"new_today": active_it_jobs.filter(first_seen__date=timezone.localdate()).count(),
"applications_open": Application.objects.filter(user=self.request.user)
.exclude(status__in=[Application.Status.REJECTED, Application.Status.WITHDRAWN])
.count(),
"source_counts": Source.objects.exclude(
domain="jobs.example.org", status=Source.Status.DISABLED
).aggregate(