@@ -0,0 +1,173 @@
|
||||
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 Q
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import reverse
|
||||
from django.views.decorators.http import require_POST
|
||||
from django.views.generic import DetailView, ListView, UpdateView
|
||||
|
||||
from apps.profiles.models import SearchProfile
|
||||
|
||||
from .forms import ApplicationForm
|
||||
from .models import Application, Feedback, JobPosting, ScoreRun
|
||||
from .services.applications import (
|
||||
build_application_export,
|
||||
build_print_html,
|
||||
delete_application_dossier,
|
||||
track_application_changes,
|
||||
)
|
||||
from .services.feedback import record_feedback
|
||||
|
||||
|
||||
class JobListView(LoginRequiredMixin, ListView):
|
||||
model = JobPosting
|
||||
template_name = "jobs/list.html"
|
||||
context_object_name = "jobs"
|
||||
paginate_by = 30
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = JobPosting.objects.select_related("employer").all()
|
||||
query = self.request.GET.get("q", "").strip()
|
||||
status = self.request.GET.get("status", "active").strip()
|
||||
workplace = self.request.GET.get("workplace", "").strip()
|
||||
if query:
|
||||
queryset = queryset.filter(
|
||||
Q(original_title__icontains=query)
|
||||
| Q(employer__name__icontains=query)
|
||||
| Q(description_text__icontains=query)
|
||||
| Q(raw_location__icontains=query)
|
||||
)
|
||||
if status:
|
||||
queryset = queryset.filter(status=status)
|
||||
if workplace:
|
||||
queryset = queryset.filter(workplace_type=workplace)
|
||||
return queryset.order_by("-first_seen")
|
||||
|
||||
|
||||
class JobDetailView(LoginRequiredMixin, DetailView):
|
||||
model = JobPosting
|
||||
template_name = "jobs/detail.html"
|
||||
context_object_name = "job"
|
||||
|
||||
def get_queryset(self):
|
||||
return JobPosting.objects.select_related("employer", "duplicate_of").prefetch_related(
|
||||
"source_aliases__source", "provenance", "versions", "feedback"
|
||||
)
|
||||
|
||||
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["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()
|
||||
return context
|
||||
|
||||
|
||||
@login_required
|
||||
def job_feedback(request, pk):
|
||||
job = get_object_or_404(JobPosting, pk=pk)
|
||||
if request.method != "POST":
|
||||
return redirect("jobs:detail", pk=pk)
|
||||
action = request.POST.get("action", "")
|
||||
valid_actions = {choice for choice, _ in Feedback.Action.choices}
|
||||
if action not in valid_actions:
|
||||
messages.error(request, "Ongeldige actie.")
|
||||
return redirect("jobs:detail", pk=pk)
|
||||
record_feedback(
|
||||
user=request.user,
|
||||
job=job,
|
||||
action=action,
|
||||
reason=request.POST.get("reason", ""),
|
||||
)
|
||||
messages.success(request, "Actie opgeslagen.")
|
||||
next_url = request.POST.get("next")
|
||||
return redirect(next_url or reverse("jobs:detail", kwargs={"pk": pk}))
|
||||
|
||||
|
||||
class ApplicationListView(LoginRequiredMixin, ListView):
|
||||
model = Application
|
||||
template_name = "applications/list.html"
|
||||
context_object_name = "applications"
|
||||
|
||||
def get_queryset(self):
|
||||
return Application.objects.filter(user=self.request.user).select_related(
|
||||
"job", "job__employer"
|
||||
)
|
||||
|
||||
|
||||
class ApplicationUpdateView(LoginRequiredMixin, UpdateView):
|
||||
model = Application
|
||||
form_class = ApplicationForm
|
||||
template_name = "applications/edit.html"
|
||||
|
||||
def get_queryset(self):
|
||||
return Application.objects.filter(user=self.request.user).select_related("job")
|
||||
|
||||
def form_valid(self, form):
|
||||
previous = {
|
||||
"status": self.object.status,
|
||||
"notes": self.object.notes,
|
||||
"contact_name": self.object.contact_name,
|
||||
"contact_email": self.object.contact_email,
|
||||
}
|
||||
response = super().form_valid(form)
|
||||
track_application_changes(
|
||||
application=self.object,
|
||||
user=self.request.user,
|
||||
previous=previous,
|
||||
current={
|
||||
"status": self.object.status,
|
||||
"notes": self.object.notes,
|
||||
"contact_name": self.object.contact_name,
|
||||
"contact_email": self.object.contact_email,
|
||||
},
|
||||
)
|
||||
return response
|
||||
|
||||
def get_success_url(self):
|
||||
messages.success(self.request, "Sollicitatiedossier opgeslagen.")
|
||||
return reverse("jobs:applications")
|
||||
|
||||
|
||||
@login_required
|
||||
def application_export(request, pk: int):
|
||||
application = get_object_or_404(
|
||||
Application.objects.filter(user=request.user).select_related("job"), pk=pk
|
||||
)
|
||||
zip_payload, filename = build_application_export(application)
|
||||
response = HttpResponse(zip_payload, content_type="application/zip")
|
||||
response["Content-Disposition"] = f'attachment; filename="{filename}"'
|
||||
return response
|
||||
|
||||
|
||||
@login_required
|
||||
def application_print(request, pk: int):
|
||||
application = get_object_or_404(
|
||||
Application.objects.filter(user=request.user).select_related("job"), pk=pk
|
||||
)
|
||||
return HttpResponse(build_print_html(application), content_type="text/html; charset=utf-8")
|
||||
|
||||
|
||||
@login_required
|
||||
@require_POST
|
||||
def application_delete(request, pk: int):
|
||||
deleted = delete_application_dossier(application_id=pk, user=request.user)
|
||||
if deleted:
|
||||
messages.success(request, "Sollicitatiedossier verwijderd.")
|
||||
else:
|
||||
messages.info(request, "Geen dossier verwijderd.")
|
||||
return redirect("jobs:applications")
|
||||
Reference in New Issue
Block a user