feat: replace dashboard and vacancy intelligence
This commit is contained in:
+26
-49
@@ -3,16 +3,7 @@ from __future__ import annotations
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.db.models import (
|
||||
CharField,
|
||||
DateTimeField,
|
||||
DecimalField,
|
||||
F,
|
||||
JSONField,
|
||||
OuterRef,
|
||||
Q,
|
||||
Subquery,
|
||||
)
|
||||
from django.db.models import Count, F, Q
|
||||
from django.http import Http404, HttpResponse
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import reverse
|
||||
@@ -30,6 +21,7 @@ from .services.applications import (
|
||||
delete_application_dossier,
|
||||
track_application_changes,
|
||||
)
|
||||
from .services.cockpit import annotate_latest_profile_score, build_job_intelligence
|
||||
from .services.feedback import record_feedback
|
||||
from .services.relevance import it_relevance_query
|
||||
from .services.skill_demand import build_skill_demand_report
|
||||
@@ -70,40 +62,15 @@ class JobListView(LoginRequiredMixin, ListView):
|
||||
VALID_SORTS = {"match", "newest", "closing"}
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = JobPosting.objects.select_related("employer").all()
|
||||
queryset = JobPosting.objects.select_related("employer").annotate(
|
||||
duplicate_count=Count("duplicates", distinct=True)
|
||||
)
|
||||
profile = SearchProfile.objects.filter(user=self.request.user, is_active=True).first()
|
||||
if profile:
|
||||
latest_score = ScoreRun.objects.filter(job=OuterRef("pk"), profile=profile).order_by(
|
||||
"-created_at"
|
||||
)
|
||||
queryset = queryset.annotate(
|
||||
match_score=Subquery(
|
||||
latest_score.values("score")[:1],
|
||||
output_field=DecimalField(max_digits=5, decimal_places=2),
|
||||
),
|
||||
match_confidence=Subquery(
|
||||
latest_score.values("confidence")[:1],
|
||||
output_field=DecimalField(max_digits=4, decimal_places=3),
|
||||
),
|
||||
match_recommendation=Subquery(
|
||||
latest_score.values("recommendation")[:1], output_field=CharField()
|
||||
),
|
||||
match_positives=Subquery(
|
||||
latest_score.values("positives")[:1], output_field=JSONField()
|
||||
),
|
||||
match_concerns=Subquery(
|
||||
latest_score.values("concerns")[:1], output_field=JSONField()
|
||||
),
|
||||
match_hard_exclusions=Subquery(
|
||||
latest_score.values("hard_exclusions")[:1], output_field=JSONField()
|
||||
),
|
||||
match_scored_at=Subquery(
|
||||
latest_score.values("created_at")[:1], output_field=DateTimeField()
|
||||
),
|
||||
)
|
||||
queryset = annotate_latest_profile_score(queryset, profile)
|
||||
query = self.request.GET.get("q", "").strip()
|
||||
status = self.request.GET.get("status", "active").strip()
|
||||
workplace = self.request.GET.get("workplace", "").strip()
|
||||
channel = self.request.GET.get("channel", "").strip()
|
||||
focus = self.request.GET.get("focus", "it").strip()
|
||||
recommendation = self.request.GET.get("match", "radar").strip()
|
||||
sort = self.request.GET.get("sort", "match").strip()
|
||||
@@ -120,6 +87,10 @@ class JobListView(LoginRequiredMixin, ListView):
|
||||
queryset = queryset.filter(status=status)
|
||||
if workplace:
|
||||
queryset = queryset.filter(workplace_type=workplace)
|
||||
if channel == "direct":
|
||||
queryset = queryset.filter(direct_employer=True, recruiter=False)
|
||||
elif channel == "recruiter":
|
||||
queryset = queryset.filter(recruiter=True)
|
||||
if focus != "all":
|
||||
queryset = queryset.filter(it_relevance_query())
|
||||
if profile and recommendation == "radar":
|
||||
@@ -162,8 +133,21 @@ class JobListView(LoginRequiredMixin, ListView):
|
||||
else "radar"
|
||||
),
|
||||
"current_sort": self.request.GET.get("sort", "match"),
|
||||
"current_channel": self.request.GET.get("channel", ""),
|
||||
}
|
||||
)
|
||||
jobs = list(context["jobs"])
|
||||
selected_id = self.request.GET.get("selected", "")
|
||||
selected_job = next((job for job in jobs if str(job.pk) == selected_id), None)
|
||||
if selected_job is None and jobs:
|
||||
selected_job = jobs[0]
|
||||
context["selected_job"] = selected_job
|
||||
if selected_job is not None:
|
||||
context["selected_intelligence"] = build_job_intelligence(
|
||||
job=selected_job,
|
||||
profile=context["active_profile"],
|
||||
user=self.request.user,
|
||||
)
|
||||
return context
|
||||
|
||||
|
||||
@@ -180,16 +164,9 @@ class JobDetailView(LoginRequiredMixin, DetailView):
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
profile = SearchProfile.objects.filter(user=self.request.user, is_active=True).first()
|
||||
context["score"] = (
|
||||
ScoreRun.objects.filter(job=self.object, profile=profile)
|
||||
.order_by("-created_at")
|
||||
.first()
|
||||
if profile
|
||||
else None
|
||||
context.update(
|
||||
build_job_intelligence(job=self.object, profile=profile, user=self.request.user)
|
||||
)
|
||||
context["application"] = Application.objects.filter(
|
||||
user=self.request.user, job=self.object
|
||||
).first()
|
||||
context["latest_feedback"] = Feedback.objects.filter(
|
||||
user=self.request.user, job=self.object
|
||||
).first()
|
||||
|
||||
Reference in New Issue
Block a user