HH/apps/appreciation/ui_views.py
Marwan Alwali 02984811ab update
2026-01-13 17:01:46 +03:00

1011 lines
33 KiB
Python

"""
Appreciation UI views - Server-rendered templates for appreciation management
"""
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.contenttypes.models import ContentType
from django.core.paginator import Paginator
from django.db.models import Q, Count
from django.http import JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.utils import timezone
from django.views.decorators.http import require_http_methods
from apps.accounts.models import User
from apps.core.services import AuditService
from apps.organizations.models import Department, Hospital, Staff
from .models import (
Appreciation,
AppreciationBadge,
AppreciationCategory,
AppreciationStatus,
AppreciationVisibility,
AppreciationStats,
UserBadge,
)
# ============================================================================
# APPRECIATION LIST & DETAIL VIEWS
# ============================================================================
@login_required
def appreciation_list(request):
"""
Appreciations list view with advanced filters and pagination.
Features:
- Server-side pagination
- Advanced filters (status, visibility, category, hospital, department)
- Search by message
- Tab-based navigation (Received, Sent, Leaderboard, Badges)
"""
# Base queryset with optimizations
queryset = Appreciation.objects.select_related(
'sender', 'hospital', 'department', 'category'
)
# Apply RBAC filters
user = request.user
if user.is_px_admin():
pass # See all
elif user.is_hospital_admin() and user.hospital:
queryset = queryset.filter(hospital=user.hospital)
elif user.is_department_manager() and user.department:
queryset = queryset.filter(
Q(department=user.department) | Q(department__isnull=True)
)
elif user.hospital:
queryset = queryset.filter(hospital=user.hospital)
else:
queryset = queryset.none()
# Apply visibility filter based on user
from django.contrib.contenttypes.models import ContentType
user_content_type = ContentType.objects.get_for_model(user)
visibility_filter = (
Q(sender=user) |
Q(recipient_content_type=user_content_type, recipient_object_id=user.id)
)
if user.department:
visibility_filter |= Q(visibility=AppreciationVisibility.DEPARTMENT, department=user.department)
if user.hospital:
visibility_filter |= Q(visibility=AppreciationVisibility.HOSPITAL, hospital=user.hospital)
visibility_filter |= Q(visibility=AppreciationVisibility.PUBLIC)
queryset = queryset.filter(visibility_filter)
# Apply filters from request
tab = request.GET.get('tab', 'received')
if tab == 'received':
# Show appreciations received by user
queryset = queryset.filter(
recipient_content_type=user_content_type,
recipient_object_id=user.id
)
elif tab == 'sent':
# Show appreciations sent by user
queryset = queryset.filter(sender=user)
# 'leaderboard' and 'badges' tabs are handled separately
status_filter = request.GET.get('status')
if status_filter:
queryset = queryset.filter(status=status_filter)
visibility_filter_req = request.GET.get('visibility')
if visibility_filter_req:
queryset = queryset.filter(visibility=visibility_filter_req)
category_filter = request.GET.get('category')
if category_filter:
queryset = queryset.filter(category_id=category_filter)
hospital_filter = request.GET.get('hospital')
if hospital_filter:
queryset = queryset.filter(hospital_id=hospital_filter)
department_filter = request.GET.get('department')
if department_filter:
queryset = queryset.filter(department_id=department_filter)
# Search
search_query = request.GET.get('search')
if search_query:
queryset = queryset.filter(
Q(message_en__icontains=search_query) |
Q(message_ar__icontains=search_query)
)
# Date range filters
date_from = request.GET.get('date_from')
if date_from:
queryset = queryset.filter(sent_at__gte=date_from)
date_to = request.GET.get('date_to')
if date_to:
queryset = queryset.filter(sent_at__lte=date_to)
# Ordering
order_by = request.GET.get('order_by', '-sent_at')
queryset = queryset.order_by(order_by)
# Pagination
page_size = int(request.GET.get('page_size', 25))
paginator = Paginator(queryset, page_size)
page_number = request.GET.get('page', 1)
page_obj = paginator.get_page(page_number)
# Get filter options
hospitals = Hospital.objects.filter(status='active')
if not user.is_px_admin() and user.hospital:
hospitals = hospitals.filter(id=user.hospital.id)
departments = Department.objects.filter(status='active')
if not user.is_px_admin() and user.hospital:
departments = departments.filter(hospital=user.hospital)
categories = AppreciationCategory.objects.filter(is_active=True)
if not user.is_px_admin() and user.hospital:
categories = categories.filter(Q(hospital_id=user.hospital.id) | Q(hospital__isnull=True))
# Statistics
user_content_type = ContentType.objects.get_for_model(user)
stats = {
'received': Appreciation.objects.filter(
recipient_content_type=user_content_type,
recipient_object_id=user.id
).count(),
'sent': Appreciation.objects.filter(sender=user).count(),
'badges_earned': UserBadge.objects.filter(
recipient_content_type=user_content_type,
recipient_object_id=user.id
).count(),
}
context = {
'page_obj': page_obj,
'appreciations': page_obj.object_list,
'stats': stats,
'hospitals': hospitals,
'departments': departments,
'categories': categories,
'status_choices': AppreciationStatus.choices,
'visibility_choices': AppreciationVisibility.choices,
'current_tab': tab,
'filters': request.GET,
}
return render(request, 'appreciation/appreciation_list.html', context)
@login_required
def appreciation_detail(request, pk):
"""
Appreciation detail view.
Features:
- Full appreciation details
- Acknowledge action for recipients
- Related appreciations
"""
appreciation = get_object_or_404(
Appreciation.objects.select_related(
'sender', 'hospital', 'department', 'category'
),
pk=pk
)
# Check access
user = request.user
from django.contrib.contenttypes.models import ContentType
user_content_type = ContentType.objects.get_for_model(user)
can_view = (
appreciation.sender == user or
(appreciation.recipient_content_type == user_content_type and
appreciation.recipient_object_id == user.id) or
user.is_px_admin() or
(user.is_hospital_admin() and appreciation.hospital == user.hospital)
)
if not can_view:
messages.error(request, "You don't have permission to view this appreciation.")
return redirect('appreciation:appreciation_list')
# Check if user is recipient
is_recipient = (
appreciation.recipient_content_type == user_content_type and
appreciation.recipient_object_id == user.id
)
# Get related appreciations
related = Appreciation.objects.filter(
recipient_content_type=appreciation.recipient_content_type,
recipient_object_id=appreciation.recipient_object_id
).exclude(pk=appreciation.pk)[:5]
context = {
'appreciation': appreciation,
'is_recipient': is_recipient,
'related': related,
'status_choices': AppreciationStatus.choices,
'visibility_choices': AppreciationVisibility.choices,
}
return render(request, 'appreciation/appreciation_detail.html', context)
@login_required
@require_http_methods(["GET", "POST"])
def appreciation_send(request):
"""Send appreciation form"""
if request.method == 'POST':
try:
# Get form data
recipient_type = request.POST.get('recipient_type')
recipient_id = request.POST.get('recipient_id')
category_id = request.POST.get('category_id', None)
message_en = request.POST.get('message_en')
message_ar = request.POST.get('message_ar', '')
visibility = request.POST.get('visibility', AppreciationVisibility.PRIVATE)
is_anonymous = request.POST.get('is_anonymous') == 'on'
hospital_id = request.POST.get('hospital_id')
department_id = request.POST.get('department_id', None)
# Validate required fields
if not all([recipient_type, recipient_id, message_en, hospital_id]):
messages.error(request, "Please fill in all required fields.")
return redirect('appreciation:appreciation_send')
# Get recipient
if recipient_type == 'user':
recipient = User.objects.get(id=recipient_id)
recipient_content_type = ContentType.objects.get_for_model(User)
else: # staff
recipient = Staff.objects.get(id=recipient_id)
recipient_content_type = ContentType.objects.get_for_model(Staff)
# Get hospital and department
hospital = Hospital.objects.get(id=hospital_id)
department = None
if department_id:
department = Department.objects.get(id=department_id)
# Get category
category = None
if category_id:
category = AppreciationCategory.objects.get(id=category_id)
# Create appreciation
appreciation = Appreciation.objects.create(
sender=request.user,
recipient_content_type=recipient_content_type,
recipient_object_id=recipient_id,
hospital=hospital,
department=department,
category=category,
message_en=message_en,
message_ar=message_ar,
visibility=visibility,
is_anonymous=is_anonymous,
)
# Send appreciation
appreciation.send()
# Log audit
AuditService.log_event(
event_type='appreciation_sent',
description=f"Appreciation sent to {str(recipient)}",
user=request.user,
content_object=appreciation,
metadata={
'visibility': visibility,
'category': category.name_en if category else None,
'anonymous': is_anonymous
}
)
messages.success(request, "Appreciation sent successfully!")
return redirect('appreciation:appreciation_detail', pk=appreciation.id)
except User.DoesNotExist:
messages.error(request, "User not found.")
except Staff.DoesNotExist:
messages.error(request, "Staff not found.")
except Exception as e:
messages.error(request, f"Error sending appreciation: {str(e)}")
return redirect('appreciation:appreciation_send')
# GET request - show form
hospitals = Hospital.objects.filter(status='active')
if not request.user.is_px_admin() and request.user.hospital:
hospitals = hospitals.filter(id=request.user.hospital.id)
categories = AppreciationCategory.objects.filter(is_active=True)
if not request.user.is_px_admin() and request.user.hospital:
categories = categories.filter(Q(hospital_id=request.user.hospital.id) | Q(hospital__isnull=True))
context = {
'hospitals': hospitals,
'categories': categories,
'visibility_choices': AppreciationVisibility.choices,
}
return render(request, 'appreciation/appreciation_send_form.html', context)
@login_required
@require_http_methods(["POST"])
def appreciation_acknowledge(request, pk):
"""Acknowledge appreciation"""
appreciation = get_object_or_404(Appreciation, pk=pk)
# Check if user is recipient
user_content_type = ContentType.objects.get_for_model(request.user)
if not (
appreciation.recipient_content_type == user_content_type and
appreciation.recipient_object_id == request.user.id
):
messages.error(request, "You can only acknowledge appreciations sent to you.")
return redirect('appreciation:appreciation_detail', pk=pk)
# Acknowledge
appreciation.acknowledge()
messages.success(request, "Appreciation acknowledged successfully.")
return redirect('appreciation:appreciation_detail', pk=pk)
# ============================================================================
# LEADERBOARD VIEWS
# ============================================================================
@login_required
def leaderboard_view(request):
"""
Appreciation leaderboard view.
Features:
- Monthly rankings
- Hospital and department filters
- Top recipients with badges
"""
user = request.user
# Get date range
now = timezone.now()
year = int(request.GET.get('year', now.year))
month = int(request.GET.get('month', now.month))
# Build base query
queryset = AppreciationStats.objects.filter(year=year, month=month)
# Apply RBAC
if not user.is_px_admin() and user.hospital:
queryset = queryset.filter(hospital=user.hospital)
# Apply filters
hospital_filter = request.GET.get('hospital')
if hospital_filter:
queryset = queryset.filter(hospital_id=hospital_filter)
department_filter = request.GET.get('department')
if department_filter:
queryset = queryset.filter(department_id=department_filter)
# Order by received count
queryset = queryset.order_by('-received_count')
# Pagination
page_size = int(request.GET.get('page_size', 50))
paginator = Paginator(queryset, page_size)
page_number = request.GET.get('page', 1)
page_obj = paginator.get_page(page_number)
# Get filter options
hospitals = Hospital.objects.filter(status='active')
if not user.is_px_admin() and user.hospital:
hospitals = hospitals.filter(id=user.hospital.id)
departments = Department.objects.filter(status='active')
if not user.is_px_admin() and user.hospital:
departments = departments.filter(hospital=user.hospital)
# Get months for filter
months = [(i, timezone.datetime(year=year, month=i, day=1).strftime('%B')) for i in range(1, 13)]
years = range(now.year - 1, now.year + 2)
context = {
'page_obj': page_obj,
'leaderboard': page_obj.object_list,
'hospitals': hospitals,
'departments': departments,
'months': months,
'years': years,
'selected_year': year,
'selected_month': month,
'filters': request.GET,
}
return render(request, 'appreciation/leaderboard.html', context)
@login_required
def my_badges_view(request):
"""
User's badges view.
Features:
- All earned badges
- Badge details and criteria
- Progress toward next badges
"""
user = request.user
user_content_type = ContentType.objects.get_for_model(user)
# Get user's badges
queryset = UserBadge.objects.filter(
recipient_content_type=user_content_type,
recipient_object_id=user.id
).select_related('badge').order_by('-earned_at')
# Pagination
page_size = int(request.GET.get('page_size', 20))
paginator = Paginator(queryset, page_size)
page_number = request.GET.get('page', 1)
page_obj = paginator.get_page(page_number)
# Get available badges for progress tracking
available_badges = AppreciationBadge.objects.filter(is_active=True)
if not request.user.is_px_admin() and request.user.hospital:
available_badges = available_badges.filter(Q(hospital_id=request.user.hospital.id) | Q(hospital__isnull=True))
# Calculate progress for each badge
badge_progress = []
total_received = Appreciation.objects.filter(
recipient_content_type=user_content_type,
recipient_object_id=user.id
).count()
for badge in available_badges:
earned = queryset.filter(badge=badge).exists()
progress = 0
if badge.criteria_type == 'count':
progress = min(100, int((total_received / badge.criteria_value) * 100))
badge_progress.append({
'badge': badge,
'earned': earned,
'progress': progress,
})
context = {
'page_obj': page_obj,
'badges': page_obj.object_list,
'total_received': total_received,
'badge_progress': badge_progress,
}
return render(request, 'appreciation/my_badges.html', context)
# ============================================================================
# ADMIN: CATEGORY MANAGEMENT
# ============================================================================
@login_required
def category_list(request):
"""List and manage appreciation categories"""
user = request.user
# Check permission
if not (user.is_px_admin() or user.is_hospital_admin()):
messages.error(request, "You don't have permission to manage categories.")
return redirect('appreciation:appreciation_list')
# Base queryset
queryset = AppreciationCategory.objects.all()
# Apply RBAC
if not user.is_px_admin() and user.hospital:
queryset = queryset.filter(Q(hospital_id=user.hospital.id) | Q(hospital__isnull=True))
# Search
search_query = request.GET.get('search')
if search_query:
queryset = queryset.filter(
Q(name_en__icontains=search_query) |
Q(name_ar__icontains=search_query) |
Q(code__icontains=search_query)
)
# Ordering
queryset = queryset.order_by('order', 'code')
# Pagination
page_size = int(request.GET.get('page_size', 25))
paginator = Paginator(queryset, page_size)
page_number = request.GET.get('page', 1)
page_obj = paginator.get_page(page_number)
context = {
'page_obj': page_obj,
'categories': page_obj.object_list,
}
return render(request, 'appreciation/admin/category_list.html', context)
@login_required
@require_http_methods(["GET", "POST"])
def category_create(request):
"""Create appreciation category"""
user = request.user
# Check permission
if not (user.is_px_admin() or user.is_hospital_admin()):
messages.error(request, "You don't have permission to create categories.")
return redirect('appreciation:appreciation_list')
if request.method == 'POST':
try:
code = request.POST.get('code')
name_en = request.POST.get('name_en')
name_ar = request.POST.get('name_ar', '')
description_en = request.POST.get('description_en', '')
description_ar = request.POST.get('description_ar', '')
icon = request.POST.get('icon', 'fa-heart')
color = request.POST.get('color', '#FF5733')
order = request.POST.get('order', 0)
is_active = request.POST.get('is_active') == 'on'
# Get hospital
hospital = None
if user.is_hospital_admin() and user.hospital:
hospital = user.hospital
# Validate
if not all([code, name_en]):
messages.error(request, "Please fill in all required fields.")
return redirect('appreciation:category_create')
# Create category
AppreciationCategory.objects.create(
code=code,
name_en=name_en,
name_ar=name_ar,
description_en=description_en,
description_ar=description_ar,
icon=icon,
color=color,
order=order,
is_active=is_active,
hospital=hospital,
)
messages.success(request, "Category created successfully.")
return redirect('appreciation:category_list')
except Exception as e:
messages.error(request, f"Error creating category: {str(e)}")
return redirect('appreciation:category_create')
context = {}
return render(request, 'appreciation/admin/category_form.html', context)
@login_required
@require_http_methods(["GET", "POST"])
def category_edit(request, pk):
"""Edit appreciation category"""
user = request.user
# Check permission
if not (user.is_px_admin() or user.is_hospital_admin()):
messages.error(request, "You don't have permission to edit categories.")
return redirect('appreciation:appreciation_list')
category = get_object_or_404(AppreciationCategory, pk=pk)
# Check access
if not user.is_px_admin() and category.hospital != user.hospital:
messages.error(request, "You don't have permission to edit this category.")
return redirect('appreciation:category_list')
if request.method == 'POST':
try:
category.code = request.POST.get('code')
category.name_en = request.POST.get('name_en')
category.name_ar = request.POST.get('name_ar', '')
category.description_en = request.POST.get('description_en', '')
category.description_ar = request.POST.get('description_ar', '')
category.icon = request.POST.get('icon', 'fa-heart')
category.color = request.POST.get('color', '#FF5733')
category.order = request.POST.get('order', 0)
category.is_active = request.POST.get('is_active') == 'on'
category.save()
messages.success(request, "Category updated successfully.")
return redirect('appreciation:category_list')
except Exception as e:
messages.error(request, f"Error updating category: {str(e)}")
return redirect('appreciation:category_edit', pk=pk)
context = {
'category': category,
}
return render(request, 'appreciation/admin/category_form.html', context)
@login_required
@require_http_methods(["POST"])
def category_delete(request, pk):
"""Delete appreciation category"""
user = request.user
# Check permission
if not (user.is_px_admin() or user.is_hospital_admin()):
messages.error(request, "You don't have permission to delete categories.")
return redirect('appreciation:appreciation_list')
category = get_object_or_404(AppreciationCategory, pk=pk)
# Check if category is in use
if Appreciation.objects.filter(category=category).exists():
messages.error(request, "Cannot delete category that is in use.")
return redirect('appreciation:category_list')
# Log audit
AuditService.log_event(
event_type='category_deleted',
description=f"Appreciation category deleted: {category.name_en}",
user=request.user,
metadata={'category_code': category.code}
)
category.delete()
messages.success(request, "Category deleted successfully.")
return redirect('appreciation:category_list')
# ============================================================================
# ADMIN: BADGE MANAGEMENT
# ============================================================================
@login_required
def badge_list(request):
"""List and manage appreciation badges"""
user = request.user
# Check permission
if not (user.is_px_admin() or user.is_hospital_admin()):
messages.error(request, "You don't have permission to manage badges.")
return redirect('appreciation:appreciation_list')
# Base queryset
queryset = AppreciationBadge.objects.all()
# Apply RBAC
if not user.is_px_admin() and user.hospital:
queryset = queryset.filter(Q(hospital_id=user.hospital.id) | Q(hospital__isnull=True))
# Search
search_query = request.GET.get('search')
if search_query:
queryset = queryset.filter(
Q(name_en__icontains=search_query) |
Q(name_ar__icontains=search_query) |
Q(code__icontains=search_query)
)
# Ordering
queryset = queryset.order_by('order', 'code')
# Pagination
page_size = int(request.GET.get('page_size', 25))
paginator = Paginator(queryset, page_size)
page_number = request.GET.get('page', 1)
page_obj = paginator.get_page(page_number)
context = {
'page_obj': page_obj,
'badges': page_obj.object_list,
}
return render(request, 'appreciation/admin/badge_list.html', context)
@login_required
@require_http_methods(["GET", "POST"])
def badge_create(request):
"""Create appreciation badge"""
user = request.user
# Check permission
if not (user.is_px_admin() or user.is_hospital_admin()):
messages.error(request, "You don't have permission to create badges.")
return redirect('appreciation:appreciation_list')
if request.method == 'POST':
try:
code = request.POST.get('code')
name_en = request.POST.get('name_en')
name_ar = request.POST.get('name_ar', '')
description_en = request.POST.get('description_en', '')
description_ar = request.POST.get('description_ar', '')
icon = request.POST.get('icon', 'fa-award')
color = request.POST.get('color', '#FFD700')
criteria_type = request.POST.get('criteria_type', 'count')
criteria_value = request.POST.get('criteria_value', 5)
order = request.POST.get('order', 0)
is_active = request.POST.get('is_active') == 'on'
# Get hospital
hospital = None
if user.is_hospital_admin() and user.hospital:
hospital = user.hospital
# Validate
if not all([code, name_en, criteria_value]):
messages.error(request, "Please fill in all required fields.")
return redirect('appreciation:badge_create')
# Create badge
AppreciationBadge.objects.create(
code=code,
name_en=name_en,
name_ar=name_ar,
description_en=description_en,
description_ar=description_ar,
icon=icon,
color=color,
criteria_type=criteria_type,
criteria_value=int(criteria_value),
order=order,
is_active=is_active,
hospital=hospital,
)
messages.success(request, "Badge created successfully.")
return redirect('appreciation:badge_list')
except Exception as e:
messages.error(request, f"Error creating badge: {str(e)}")
return redirect('appreciation:badge_create')
context = {}
return render(request, 'appreciation/admin/badge_form.html', context)
@login_required
@require_http_methods(["GET", "POST"])
def badge_edit(request, pk):
"""Edit appreciation badge"""
user = request.user
# Check permission
if not (user.is_px_admin() or user.is_hospital_admin()):
messages.error(request, "You don't have permission to edit badges.")
return redirect('appreciation:appreciation_list')
badge = get_object_or_404(AppreciationBadge, pk=pk)
# Check access
if not user.is_px_admin() and badge.hospital != user.hospital:
messages.error(request, "You don't have permission to edit this badge.")
return redirect('appreciation:badge_list')
if request.method == 'POST':
try:
badge.code = request.POST.get('code')
badge.name_en = request.POST.get('name_en')
badge.name_ar = request.POST.get('name_ar', '')
badge.description_en = request.POST.get('description_en', '')
badge.description_ar = request.POST.get('description_ar', '')
badge.icon = request.POST.get('icon', 'fa-award')
badge.color = request.POST.get('color', '#FFD700')
badge.criteria_type = request.POST.get('criteria_type', 'count')
badge.criteria_value = request.POST.get('criteria_value', 5)
badge.order = request.POST.get('order', 0)
badge.is_active = request.POST.get('is_active') == 'on'
badge.save()
messages.success(request, "Badge updated successfully.")
return redirect('appreciation:badge_list')
except Exception as e:
messages.error(request, f"Error updating badge: {str(e)}")
return redirect('appreciation:badge_edit', pk=pk)
context = {
'badge': badge,
}
return render(request, 'appreciation/admin/badge_form.html', context)
@login_required
@require_http_methods(["POST"])
def badge_delete(request, pk):
"""Delete appreciation badge"""
user = request.user
# Check permission
if not (user.is_px_admin() or user.is_hospital_admin()):
messages.error(request, "You don't have permission to delete badges.")
return redirect('appreciation:appreciation_list')
badge = get_object_or_404(AppreciationBadge, pk=pk)
# Check if badge is in use
if UserBadge.objects.filter(badge=badge).exists():
messages.error(request, "Cannot delete badge that has been earned.")
return redirect('appreciation:badge_list')
# Log audit
AuditService.log_event(
event_type='badge_deleted',
description=f"Appreciation badge deleted: {badge.name_en}",
user=request.user,
metadata={'badge_code': badge.code}
)
badge.delete()
messages.success(request, "Badge deleted successfully.")
return redirect('appreciation:badge_list')
# ============================================================================
# AJAX/API HELPERS
# ============================================================================
@login_required
def get_users_by_hospital(request):
"""Get users for a hospital (AJAX)"""
hospital_id = request.GET.get('hospital_id')
if not hospital_id:
return JsonResponse({'users': []})
users = User.objects.filter(
hospital_id=hospital_id,
is_active=True
).values('id', 'first_name', 'last_name')
results = [
{
'id': str(u['id']),
'name': f"{u['first_name']} {u['last_name']}",
}
for u in users
]
return JsonResponse({'users': results})
@login_required
def get_staff_by_hospital(request):
"""Get staff for a hospital (AJAX)"""
hospital_id = request.GET.get('hospital_id')
if not hospital_id:
return JsonResponse({'staff': []})
staff = Staff.objects.filter(
hospital_id=hospital_id,
status='active'
).values('id', 'user__first_name', 'user__last_name')
results = [
{
'id': str(s['id']),
'name': f"{s['user__first_name']} {s['user__last_name']}",
}
for s in staff
]
return JsonResponse({'staff': results})
@login_required
def get_physicians_by_hospital(request):
"""Get physicians for a hospital (AJAX)"""
hospital_id = request.GET.get('hospital_id')
if not hospital_id:
return JsonResponse({'physicians': []})
physicians = Staff.objects.filter(
hospital_id=hospital_id,
status='active',
staff_type='physician'
).values('id', 'user__first_name', 'user__last_name')
results = [
{
'id': str(p['id']),
'name': f"{p['user__first_name']} {p['user__last_name']}",
}
for p in physicians
]
return JsonResponse({'physicians': results})
@login_required
def get_departments_by_hospital(request):
"""Get departments for a hospital (AJAX)"""
hospital_id = request.GET.get('hospital_id')
if not hospital_id:
return JsonResponse({'departments': []})
departments = Department.objects.filter(
hospital_id=hospital_id,
status='active'
).values('id', 'name', 'name_ar')
results = [
{
'id': str(d['id']),
'name': d['name'],
}
for d in departments
]
return JsonResponse({'departments': results})
@login_required
def appreciation_summary_ajax(request):
"""Get appreciation summary for current user (AJAX)"""
user = request.user
user_content_type = ContentType.objects.get_for_model(user)
now = timezone.now()
current_year = now.year
current_month = now.month
summary = {
'total_received': Appreciation.objects.filter(
recipient_content_type=user_content_type,
recipient_object_id=user.id
).count(),
'total_sent': Appreciation.objects.filter(sender=user).count(),
'this_month_received': Appreciation.objects.filter(
recipient_content_type=user_content_type,
recipient_object_id=user.id,
sent_at__year=current_year,
sent_at__month=current_month
).count(),
'this_month_sent': Appreciation.objects.filter(
sender=user,
sent_at__year=current_year,
sent_at__month=current_month
).count(),
'badges_earned': UserBadge.objects.filter(
recipient_content_type=user_content_type,
recipient_object_id=user.id
).count(),
}
# Get hospital rank
if user.hospital:
stats = AppreciationStats.objects.filter(
recipient_content_type=user_content_type,
recipient_object_id=user.id,
year=current_year,
month=current_month
).first()
summary['hospital_rank'] = stats.hospital_rank if stats else None
return JsonResponse(summary)