from __future__ import annotations from typing import Any from django.db.models import Avg, Count, Max, Q, QuerySet from apps.profiles.models import SearchProfile from apps.sources.models import Source from ..models import Application, Employer, JobPosting, ScoreRun from .cockpit import annotate_latest_profile_score from .relevance import it_relevance_query def employer_index_queryset(*, user, profile: SearchProfile | None) -> QuerySet[Employer]: score_filter = Q(jobs__scores__profile=profile) if profile else Q(pk__isnull=True) return Employer.objects.annotate( active_vacancies=Count( "jobs", filter=Q(jobs__status=JobPosting.Status.ACTIVE), distinct=True ), relevant_vacancies=Count( "jobs", filter=Q(jobs__status=JobPosting.Status.ACTIVE) & it_relevance_query("jobs__"), distinct=True, ), previous_applications=Count( "jobs__applications", filter=Q(jobs__applications__user=user), distinct=True, ), source_count=Count("jobs__source_aliases__source", distinct=True), latest_job_at=Max("jobs__first_seen"), average_match=Avg("jobs__scores__score", filter=score_filter), ) def filter_employers( queryset: QuerySet[Employer], *, query: str = "", channel: str = "", active_only: bool = False ) -> QuerySet[Employer]: if query.strip(): queryset = queryset.filter( Q(name__icontains=query.strip()) | Q(domain__icontains=query.strip()) | Q(jobs__raw_location__icontains=query.strip()) ) if channel == "direct": queryset = queryset.filter(is_direct_employer=True, is_recruiter=False) elif channel == "recruiter": queryset = queryset.filter(is_recruiter=True) if active_only: queryset = queryset.filter(active_vacancies__gt=0) return queryset.order_by("-relevant_vacancies", "-active_vacancies", "name").distinct() def build_employer_detail( *, employer: Employer, user, profile: SearchProfile | None ) -> dict[str, Any]: jobs = annotate_latest_profile_score( employer.jobs.select_related("employer").all(), profile ).order_by("-first_seen") sources = Source.objects.filter(job_aliases__job__employer=employer).distinct().order_by("name") locations = list( employer.jobs.exclude(raw_location="") .order_by("raw_location") .values_list("raw_location", flat=True) .distinct()[:8] ) return { "employer": employer, "recent_jobs": list(jobs[:12]), "active_jobs": list(jobs.filter(status=JobPosting.Status.ACTIVE)[:8]), "applications": list( Application.objects.filter(user=user, job__employer=employer) .select_related("job") .order_by("-updated_at")[:8] ), "sources": list(sources[:10]), "locations": locations, "match_history": list( ScoreRun.objects.filter(profile=profile, job__employer=employer) .select_related("job") .order_by("-created_at")[:20] ) if profile else [], }