142 lines
5.9 KiB
Python
142 lines
5.9 KiB
Python
from django.shortcuts import render, redirect, get_object_or_404
|
|
from django.utils import timezone
|
|
from django.db.models import Sum
|
|
from decimal import Decimal
|
|
from .models import Worker, Project, WorkLog, Team, PayrollRecord, Loan, PayrollAdjustment
|
|
from .forms import AttendanceLogForm
|
|
from django.contrib import messages
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.http import JsonResponse, HttpResponseForbidden
|
|
|
|
def is_admin(user):
|
|
return user.is_staff or user.is_superuser
|
|
|
|
def is_supervisor(user):
|
|
return user.supervised_teams.exists() or user.assigned_projects.exists() or user.groups.filter(name='Work Logger').exists()
|
|
|
|
def is_staff_or_supervisor(user):
|
|
return is_admin(user) or is_supervisor(user)
|
|
|
|
# Home view for the dashboard
|
|
@login_required
|
|
def index(request):
|
|
user = request.user
|
|
|
|
if is_admin(user):
|
|
# Calculate total value of unpaid work and break it down by project
|
|
unpaid_worklogs = WorkLog.objects.filter(payroll_records__isnull=True).prefetch_related('workers', 'project')
|
|
outstanding_payments = Decimal('0.00')
|
|
outstanding_by_project = {}
|
|
|
|
for wl in unpaid_worklogs:
|
|
project_name = wl.project.name
|
|
if project_name not in outstanding_by_project:
|
|
outstanding_by_project[project_name] = Decimal('0.00')
|
|
for worker in wl.workers.all():
|
|
cost = worker.daily_rate
|
|
outstanding_payments += cost
|
|
outstanding_by_project[project_name] += cost
|
|
|
|
# Include unpaid payroll adjustments in the outstanding calculations
|
|
unpaid_adjustments = PayrollAdjustment.objects.filter(payroll_record__isnull=True)
|
|
for adj in unpaid_adjustments:
|
|
outstanding_payments += adj.amount
|
|
project_name = adj.project.name if adj.project else 'General'
|
|
if project_name not in outstanding_by_project:
|
|
outstanding_by_project[project_name] = Decimal('0.00')
|
|
outstanding_by_project[project_name] += adj.amount
|
|
|
|
# Sum the total amount paid out over the last 60 days
|
|
sixty_days_ago = timezone.now().date() - timezone.timedelta(days=60)
|
|
paid_this_month = PayrollRecord.objects.filter(date__gte=sixty_days_ago).aggregate(total=Sum('amount_paid'))['total'] or Decimal('0.00')
|
|
|
|
# Tally the count and total balance of active loans
|
|
active_loans_qs = Loan.objects.filter(active=True)
|
|
active_loans_count = active_loans_qs.count()
|
|
active_loans_balance = active_loans_qs.aggregate(total=Sum('remaining_balance'))['total'] or Decimal('0.00')
|
|
|
|
start_of_week = timezone.now().date() - timezone.timedelta(days=timezone.now().date().weekday())
|
|
this_week_logs = WorkLog.objects.filter(date__gte=start_of_week).count()
|
|
|
|
recent_activity = WorkLog.objects.all().order_by('-date', '-id')[:5]
|
|
|
|
# Get all workers, projects, and teams for the Manage Resources tab
|
|
workers = Worker.objects.all().order_by('name')
|
|
projects = Project.objects.all().order_by('name')
|
|
teams = Team.objects.all().order_by('name')
|
|
|
|
context = {
|
|
'is_admin': True,
|
|
'outstanding_payments': outstanding_payments,
|
|
'paid_this_month': paid_this_month,
|
|
'active_loans_count': active_loans_count,
|
|
'active_loans_balance': active_loans_balance,
|
|
'outstanding_by_project': outstanding_by_project,
|
|
'this_week_logs': this_week_logs,
|
|
'recent_activity': recent_activity,
|
|
'workers': workers,
|
|
'projects': projects,
|
|
'teams': teams,
|
|
}
|
|
return render(request, 'core/index.html', context)
|
|
else:
|
|
start_of_week = timezone.now().date() - timezone.timedelta(days=timezone.now().date().weekday())
|
|
this_week_logs = WorkLog.objects.filter(date__gte=start_of_week, supervisor=user).count()
|
|
recent_activity = WorkLog.objects.filter(supervisor=user).order_by('-date', '-id')[:5]
|
|
|
|
context = {
|
|
'is_admin': False,
|
|
'this_week_logs': this_week_logs,
|
|
'recent_activity': recent_activity,
|
|
}
|
|
return render(request, 'core/index.html', context)
|
|
|
|
# View for logging attendance
|
|
@login_required
|
|
def attendance_log(request):
|
|
if request.method == 'POST':
|
|
form = AttendanceLogForm(request.POST)
|
|
if form.is_valid():
|
|
form.save()
|
|
messages.success(request, 'Attendance logged successfully!')
|
|
return redirect('home')
|
|
else:
|
|
form = AttendanceLogForm(initial={'date': timezone.now().date(), 'supervisor': request.user})
|
|
|
|
return render(request, 'core/attendance_log.html', {'form': form})
|
|
|
|
# Work history view
|
|
@login_required
|
|
def work_history(request):
|
|
if is_admin(request.user):
|
|
logs = WorkLog.objects.all().order_by('-date', '-id')
|
|
else:
|
|
logs = WorkLog.objects.filter(supervisor=request.user).order_by('-date', '-id')
|
|
return render(request, 'core/work_history.html', {'logs': logs})
|
|
|
|
# API view to toggle resource active status
|
|
@login_required
|
|
def toggle_active(request, model_name, item_id):
|
|
if request.method != 'POST':
|
|
return HttpResponseForbidden("Only POST requests are allowed.")
|
|
|
|
if not is_admin(request.user):
|
|
return HttpResponseForbidden("Not authorized.")
|
|
|
|
model_map = {
|
|
'worker': Worker,
|
|
'project': Project,
|
|
'team': Team
|
|
}
|
|
|
|
if model_name not in model_map:
|
|
return JsonResponse({'error': 'Invalid model'}, status=400)
|
|
|
|
model = model_map[model_name]
|
|
try:
|
|
item = model.objects.get(id=item_id)
|
|
item.active = not item.active
|
|
item.save()
|
|
return JsonResponse({'status': 'success', 'active': item.active})
|
|
except model.DoesNotExist:
|
|
return JsonResponse({'error': 'Item not found'}, status=404) |