import os import platform from django.shortcuts import render, redirect, get_object_or_404 from django.contrib.auth import login, logout, authenticate 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 .models import Company, Profile, JobStatus, RequiredFolder, Job, JobFolderCompletion from .forms import CompanyForm, JobStatusForm, RequiredFolderForm, JobForm def home(request): if request.user.is_authenticated: return redirect('dashboard') context = { "project_name": "RepairsHub", } return render(request, "core/index.html", context) def register_view(request): if request.method == 'POST': form = UserCreationForm(request.POST) if form.is_valid(): user = form.save() login(request, user) return redirect('company_setup') else: form = UserCreationForm() return render(request, 'core/register.html', {'form': form}) def login_view(request): if request.method == 'POST': form = AuthenticationForm(data=request.POST) if form.is_valid(): user = form.get_user() login(request, user) return redirect('dashboard') else: form = AuthenticationForm() return render(request, 'core/login.html', {'form': form}) def logout_view(request): logout(request) return redirect('home') @login_required def company_setup(request): # Check if user already has a company if request.user.profile.company: return redirect('dashboard') if request.method == 'POST': company_form = CompanyForm(request.POST) status_names = request.POST.getlist('statuses') default_status_idx = request.POST.get('default_status') folder_names = request.POST.getlist('folders') if company_form.is_valid() and status_names and default_status_idx is not None: with transaction.atomic(): company = company_form.save() # Link user to company as ADMIN profile = request.user.profile profile.company = company profile.role = 'ADMIN' profile.save() # Create statuses for i, name in enumerate(status_names): if name.strip(): JobStatus.objects.create( company=company, name=name.strip(), is_starting_status=(str(i) == default_status_idx), order=i ) # Create folders for name in folder_names: if name.strip(): RequiredFolder.objects.create( company=company, name=name.strip() ) messages.success(request, f"Company {company.name} created successfully!") return redirect('dashboard') else: if not status_names: messages.error(request, "At least one status is required.") if default_status_idx is None: messages.error(request, "You must select a starting status.") else: company_form = CompanyForm() return render(request, 'core/company_setup.html', { 'company_form': company_form, }) @login_required def dashboard(request): profile = request.user.profile if not profile.company: return redirect('company_setup') company = profile.company jobs = Job.objects.filter(company=company) context = { 'company': company, 'total_jobs': jobs.count(), 'jobs': jobs.order_by('-created_at')[:5], # Recent jobs } return render(request, 'core/dashboard.html', context) @login_required def job_list(request): profile = request.user.profile if not profile.company: return redirect('company_setup') company = profile.company jobs = Job.objects.filter(company=company).order_by('-created_at') return render(request, 'core/job_list.html', { 'jobs': jobs, 'company': company }) @login_required def job_create(request): profile = request.user.profile if not profile.company: return redirect('company_setup') company = profile.company if request.method == 'POST': form = JobForm(request.POST, company=company) if form.is_valid(): job = form.save(commit=False) job.company = company job.save() # Initialize folder completions for folder in company.required_folders.all(): JobFolderCompletion.objects.get_or_create(job=job, folder=folder) messages.success(request, f"Job {job.job_ref} created successfully!") return redirect('job_detail', pk=job.pk) else: form = JobForm(company=company) return render(request, 'core/job_form.html', { 'form': form, 'title': 'Create New Job', 'company': company }) @login_required def job_detail(request, pk): profile = request.user.profile if not profile.company: return redirect('company_setup') company = profile.company job = get_object_or_404(Job, pk=pk, company=company) # Ensure all required folders have completion records (in case new ones were added later) for folder in company.required_folders.all(): JobFolderCompletion.objects.get_or_create(job=job, folder=folder) folder_completions = job.folder_completions.all().select_related('folder') return render(request, 'core/job_detail.html', { 'job': job, 'folder_completions': folder_completions, 'company': company }) @login_required def job_update(request, pk): profile = request.user.profile if not profile.company: return redirect('company_setup') company = profile.company job = get_object_or_404(Job, pk=pk, company=company) if request.method == 'POST': form = JobForm(request.POST, instance=job, company=company) if form.is_valid(): form.save() messages.success(request, f"Job {job.job_ref} updated successfully!") return redirect('job_detail', pk=job.pk) else: form = JobForm(instance=job, company=company) return render(request, 'core/job_form.html', { 'form': form, 'title': f'Edit Job: {job.job_ref}', 'company': company }) @login_required def job_delete(request, pk): profile = request.user.profile if not profile.company: return redirect('company_setup') company = profile.company job = get_object_or_404(Job, pk=pk, company=company) if request.method == 'POST': job_ref = job.job_ref job.delete() messages.success(request, f"Job {job_ref} deleted.") return redirect('job_list') return render(request, 'core/job_confirm_delete.html', { 'job': job, 'company': company }) @login_required def toggle_folder_completion(request, pk, folder_id): profile = request.user.profile if not profile.company: return redirect('company_setup') company = profile.company job = get_object_or_404(Job, pk=pk, company=company) completion = get_object_or_404(JobFolderCompletion, job=job, folder_id=folder_id) completion.is_completed = not completion.is_completed completion.save() messages.success(request, f"Folder '{completion.folder.name}' status updated.") return redirect('job_detail', pk=job.pk) @login_required def settings_view(request): profile = request.user.profile if not profile.company: return redirect('company_setup') if profile.role != 'ADMIN': messages.error(request, "Only admins can access company settings.") return redirect('dashboard') company = profile.company statuses = company.statuses.all() folders = company.required_folders.all() return render(request, 'core/settings.html', { 'company': company, 'statuses': statuses, 'folders': folders }) @login_required def status_create(request): profile = request.user.profile if profile.role != 'ADMIN': return redirect('dashboard') if request.method == 'POST': form = JobStatusForm(request.POST) if form.is_valid(): status = form.save(commit=False) status.company = profile.company if status.is_starting_status: # Unset other starting statuses JobStatus.objects.filter(company=profile.company).update(is_starting_status=False) status.save() messages.success(request, "New status created.") return redirect('settings') else: form = JobStatusForm() return render(request, 'core/status_form.html', {'form': form, 'title': 'Create Status'}) @login_required def status_update(request, pk): profile = request.user.profile if profile.role != 'ADMIN': return redirect('dashboard') status = get_object_or_404(JobStatus, pk=pk, company=profile.company) if request.method == 'POST': form = JobStatusForm(request.POST, instance=status) if form.is_valid(): if form.cleaned_data['is_starting_status']: JobStatus.objects.filter(company=profile.company).update(is_starting_status=False) form.save() messages.success(request, "Status updated.") return redirect('settings') else: form = JobStatusForm(instance=status) return render(request, 'core/status_form.html', {'form': form, 'title': 'Edit Status'}) @login_required def status_delete(request, pk): profile = request.user.profile if profile.role != 'ADMIN': return redirect('dashboard') status = get_object_or_404(JobStatus, pk=pk, company=profile.company) if status.is_starting_status: messages.error(request, "Cannot delete the starting status. Please set another status as starting first.") return redirect('settings') if request.method == 'POST': starting_status = profile.company.statuses.filter(is_starting_status=True).first() Job.objects.filter(status=status).update(status=starting_status) status.delete() messages.success(request, f"Status deleted. Jobs reassigned to {starting_status.name}.") return redirect('settings') return render(request, 'core/status_confirm_delete.html', {'status': status}) @login_required def folder_create(request): profile = request.user.profile if profile.role != 'ADMIN': return redirect('dashboard') if request.method == 'POST': form = RequiredFolderForm(request.POST) if form.is_valid(): folder = form.save(commit=False) folder.company = profile.company folder.save() # Note: The jobs will automatically see this new folder in job_detail view messages.success(request, f"Folder '{folder.name}' added company-wide.") return redirect('settings') else: form = RequiredFolderForm() return render(request, 'core/folder_form.html', {'form': form}) @login_required def folder_delete(request, pk): profile = request.user.profile if profile.role != 'ADMIN': return redirect('dashboard') folder = get_object_or_404(RequiredFolder, pk=pk, company=profile.company) if request.method == 'POST': folder.delete() messages.success(request, "Folder removed from company settings.") return redirect('settings') return render(request, 'core/folder_confirm_delete.html', {'folder': folder})