From 2cfab7c3efde5a92532252ab991898b997f22942 Mon Sep 17 00:00:00 2001 From: Faheed Date: Thu, 30 Oct 2025 19:54:09 +0300 Subject: [PATCH] spinner for parsing --- .../__pycache__/models.cpython-312.pyc | Bin 84639 -> 84139 bytes .../views_frontend.cpython-312.pyc | Bin 45495 -> 46514 bytes recruitment/models.py | 32 +----- recruitment/views_frontend.py | 28 +++++- templates/base.html | 1 - .../jobs/partials/linkedin_content_form.html | 2 +- templates/recruitment/candidate_detail.html | 52 ++++------ .../recruitment/candidate_interview_view.html | 34 +++++-- .../recruitment/candidate_screening_view.html | 2 +- templates/recruitment/dashboard.html | 94 ++++++++++++++++++ 10 files changed, 163 insertions(+), 82 deletions(-) diff --git a/recruitment/__pycache__/models.cpython-312.pyc b/recruitment/__pycache__/models.cpython-312.pyc index fff953ce715002fc65889d40bd9cc5bdd4293059..7e98f6b79a34a1929c20ad36cc99760d43e710d8 100644 GIT binary patch delta 4341 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 diff --git a/recruitment/__pycache__/views_frontend.cpython-312.pyc b/recruitment/__pycache__/views_frontend.cpython-312.pyc index 4c1b0db179447afc237198cbb5f59fe9e5b32619..a19c31f90751687e0c9f3529b10dc6424052dc66 100644 GIT binary patch delta 4793 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 delta 3914 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 I@%VG>|K8O|yZ`_I diff --git a/recruitment/models.py b/recruitment/models.py index 4ed1316..0b406f8 100644 --- a/recruitment/models.py +++ b/recruitment/models.py @@ -680,36 +680,8 @@ class Candidate(Base): return future_meetings or today_future_meetings @property - def check_and_retry_ai_scoring(self): - """ - Triggers an immediate save ONLY if: - 1. The resume hasn't been parsed yet. - 2. At least 5 minutes have passed since the last attempt. - Returns True if a save was performed, False otherwise. - """ - from datetime import timedelta - - min_delay = timedelta(minutes=5) - - time_since_last_attempt = timezone.now() - self.created_at - - if not self.is_resume_parsed and time_since_last_attempt >= min_delay: - - # 1. Update the retry timestamp - self.last_retry_attempt = timezone.now() - - - self.save() - - return True - - return False - - # @property - # def time_to_hire(self): - # time_to_hire=self.hired_date-self.created_at - # return time_to_hire - + def scoring_timeout(self): + return timezone.now() <= (self.created_at + timezone.timedelta(minutes=5)) class TrainingMaterial(Base): diff --git a/recruitment/views_frontend.py b/recruitment/views_frontend.py index b403475..729749e 100644 --- a/recruitment/views_frontend.py +++ b/recruitment/views_frontend.py @@ -223,10 +223,17 @@ class CandidateDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteView): def retry_scoring_view(request,slug): - if request.method == 'POST': - candidate = get_object_or_404(models.Candidate, slug=slug) - candidate.save() - return redirect('candidate_detail', slug=candidate.slug) + from django_q.tasks import async_task + + candidate = get_object_or_404(models.Candidate, slug=slug) + + async_task( + 'recruitment.tasks.handle_reume_parsing_and_scoring', + candidate.pk, + hook='recruitment.hooks.callback_ai_parsing', + sync=True, + ) + return redirect('candidate_detail', slug=candidate.slug) @@ -507,6 +514,15 @@ def dashboard_view(request): rotation_degrees = rotation_percent * 180 rotation_degrees_final = round(min(rotation_degrees, 180), 1) # Ensure max 180 degrees + # + hiring_source_counts = candidate_queryset.values('hiring_source').annotate(count=Count('stage')) + source_map= {item['hiring_source']: item['count'] for item in hiring_source_counts} + candidates_count_in_each_source = [ + source_map.get('Public', 0), source_map.get('Internal', 0), source_map.get('Agency', 0), + + ] + all_hiring_sources=["Public", "Internal", "Agency"] + # --- 8. CONTEXT RETURN --- @@ -555,6 +571,10 @@ def dashboard_view(request): 'jobs': all_jobs_queryset, 'current_job_id': selected_job_pk, 'current_job': current_job, + + + 'candidates_count_in_each_source': json.dumps(candidates_count_in_each_source), + 'all_hiring_sources': json.dumps(all_hiring_sources), } return render(request, 'recruitment/dashboard.html', context) diff --git a/templates/base.html b/templates/base.html index 7a394ab..eef4251 100644 --- a/templates/base.html +++ b/templates/base.html @@ -705,6 +705,5 @@ {% comment %} {% endif %} {% endcomment %} {% block customJS %}{% endblock %} - diff --git a/templates/jobs/partials/linkedin_content_form.html b/templates/jobs/partials/linkedin_content_form.html index 9a606e7..c3edd5a 100644 --- a/templates/jobs/partials/linkedin_content_form.html +++ b/templates/jobs/partials/linkedin_content_form.html @@ -1,6 +1,6 @@ {% load crispy_forms_tags %}