diff --git a/assets/pasted-20260122-091742-8812311a.png b/assets/pasted-20260122-091742-8812311a.png new file mode 100644 index 0000000..6b6a77d Binary files /dev/null and b/assets/pasted-20260122-091742-8812311a.png differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 4c75d13..16832d8 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/templates/core/dashboard.html b/core/templates/core/dashboard.html index 7d55a4d..5ba1230 100644 --- a/core/templates/core/dashboard.html +++ b/core/templates/core/dashboard.html @@ -130,7 +130,7 @@
-
Incomplete Folder Breakdown
+
Incomplete Folder Breakdown (Overall)
{% if incomplete_folder_breakdown %}
    {% for item in incomplete_folder_breakdown %} @@ -149,45 +149,57 @@
-
-
-
Jobs by Client
-
-
- {% if jobs_by_client %} - {% for client_name, client_jobs in jobs_by_client.items %} -
{{ client_name }} ({{ client_jobs|length }} Jobs)
-
- - - - - - - - - - - {% for job in client_jobs %} - - - - - - - {% endfor %} - -
Job RefAddressStatusActions
{{ job.job_ref }}{{ job.address_line_1 }}, {{ job.postcode }}{{ job.status.name }} - View -
+ {# Client-specific breakdown #} + {% if client_stats %} + {% for client_stat in client_stats %} +
+
+
{{ client_stat.client_name }}
+
+
+
+
+
+
{{ client_stat.total_jobs }}
+
Total Jobs
+
- {% endfor %} - {% else %} -

No jobs found or clients assigned.

- {% endif %} +
+
+
{{ client_stat.incomplete_jobs }}
+
Jobs with Incomplete Folders
+
+
+
+
+
Incomplete Folders
+ {% if client_stat.incomplete_folder_breakdown %} + + {% else %} +

All folders complete.

+ {% endif %} +
+
+
+
-
- + {% endfor %} + {% else %} +
+
+

No client-specific job data available.

+
+
+ {% endif %}
diff --git a/core/views.py b/core/views.py index 2532ad1..de75828 100644 --- a/core/views.py +++ b/core/views.py @@ -10,7 +10,7 @@ from django.contrib.auth.forms import UserCreationForm, AuthenticationForm from django.contrib.auth.decorators import login_required from django.contrib import messages from django.db import transaction -from django.db.models import Count +from django.db.models import Count, Q from django.http import HttpResponse from django.core.mail import send_mail from django.conf import settings @@ -114,7 +114,7 @@ def dashboard(request): return redirect('company_setup') company = profile.company - jobs = Job.objects.filter(company=company).select_related('client') + jobs = Job.objects.filter(company=company).select_related('client', 'status') total_jobs = jobs.count() @@ -129,8 +129,7 @@ def dashboard(request): for folder in required_folders: # Count jobs where this specific folder is NOT completed - missing_count = Job.objects.filter( - company=company, + missing_count = jobs.filter( folder_completions__folder=folder, folder_completions__is_completed=False ).distinct().count() @@ -141,13 +140,62 @@ def dashboard(request): 'missing_count': missing_count }) - # NEW LOGIC: Group jobs by client - jobs_by_client = {} - for job in jobs: - client_name = job.client.name if job.client else "No Client Assigned" - if client_name not in jobs_by_client: - jobs_by_client[client_name] = [] - jobs_by_client[client_name].append(job) + # NEW LOGIC: Group jobs by client with detailed statistics + client_stats = [] + clients = company.clients.all() + + # Add a "No Client Assigned" entry first if there are jobs without a client + jobs_no_client = jobs.filter(client__isnull=True) + if jobs_no_client.exists(): + no_client_total_jobs = jobs_no_client.count() + no_client_incomplete_jobs = jobs_no_client.filter(folder_completions__is_completed=False).distinct().count() + + no_client_incomplete_folder_breakdown = [] + for folder in required_folders: + missing_count = jobs_no_client.filter( + folder_completions__folder=folder, + folder_completions__is_completed=False + ).distinct().count() + if missing_count > 0: + no_client_incomplete_folder_breakdown.append({ + 'folder_name': folder.name, + 'missing_count': missing_count, + 'folder_id': folder.id + }) + client_stats.append({ + 'client_name': "No Client Assigned", + 'total_jobs': no_client_total_jobs, + 'incomplete_jobs': no_client_incomplete_jobs, + 'incomplete_folder_breakdown': no_client_incomplete_folder_breakdown + }) + + for client in clients: + client_jobs = jobs.filter(client=client) + total_client_jobs = client_jobs.count() + + if total_client_jobs > 0: # Only include clients with jobs + client_incomplete_jobs = client_jobs.filter(folder_completions__is_completed=False).distinct().count() + + client_incomplete_folder_breakdown = [] + for folder in required_folders: + missing_count = client_jobs.filter( + folder_completions__folder=folder, + folder_completions__is_completed=False + ).distinct().count() + if missing_count > 0: + client_incomplete_folder_breakdown.append({ + 'folder_name': folder.name, + 'missing_count': missing_count, + 'folder_id': folder.id + }) + + client_stats.append({ + 'client_name': client.name, + 'total_jobs': total_client_jobs, + 'incomplete_jobs': client_incomplete_jobs, + 'incomplete_folder_breakdown': client_incomplete_folder_breakdown + }) + context = { 'company': company, @@ -156,7 +204,7 @@ def dashboard(request): 'jobs_with_incomplete_folders': jobs_with_incomplete_folders, 'jobs': jobs.order_by('-created_at')[:5], 'incomplete_folder_breakdown': incomplete_folder_breakdown, - 'jobs_by_client': jobs_by_client, + 'client_stats': client_stats, # Replaced jobs_by_client } return render(request, 'core/dashboard.html', context) @@ -277,6 +325,8 @@ def job_delete(request, pk): job = get_object_or_404(Job, pk=pk, company=company) if request.method == 'POST': + # You might want to add a check here if there are any jobs associated with this client + # If jobs are associated, you might want to reassign them or prevent deletion. job_ref = job.job_ref job.delete() messages.success(request, f"Job {job_ref} deleted.") @@ -781,4 +831,4 @@ def user_delete(request, pk): user_to_delete.delete() messages.success(request, f"User {username} deleted.") - return redirect('user_list') \ No newline at end of file + return redirect('user_list') diff --git a/staticfiles/pasted-20260122-091742-8812311a.png b/staticfiles/pasted-20260122-091742-8812311a.png new file mode 100644 index 0000000..6b6a77d Binary files /dev/null and b/staticfiles/pasted-20260122-091742-8812311a.png differ