150 lines
5.1 KiB
Python
150 lines
5.1 KiB
Python
from django.contrib import admin
|
|
from django.utils.html import format_html
|
|
from .models import JobPosition, JobApplication
|
|
|
|
|
|
@admin.register(JobPosition)
|
|
class JobPositionAdmin(admin.ModelAdmin):
|
|
list_display = [
|
|
'title',
|
|
'department',
|
|
'location',
|
|
'open_positions',
|
|
'employment_type',
|
|
'status_badge',
|
|
'featured',
|
|
'posted_date',
|
|
'applications_count'
|
|
]
|
|
list_filter = ['status', 'employment_type', 'location_type', 'featured', 'department', 'posted_date']
|
|
search_fields = ['title', 'department', 'location', 'short_description']
|
|
prepopulated_fields = {'slug': ('title',)}
|
|
readonly_fields = ['posted_date', 'updated_date', 'applications_count']
|
|
|
|
fieldsets = (
|
|
('Basic Information', {
|
|
'fields': ('title', 'slug', 'department', 'status', 'featured', 'priority')
|
|
}),
|
|
('Employment Details', {
|
|
'fields': ('employment_type', 'location_type', 'location', 'open_positions', 'experience_required')
|
|
}),
|
|
('Salary Information', {
|
|
'fields': ('salary_min', 'salary_max', 'salary_currency', 'salary_period', 'salary_additional')
|
|
}),
|
|
('Job Description', {
|
|
'fields': ('short_description', 'about_role')
|
|
}),
|
|
('Requirements & Qualifications', {
|
|
'fields': ('requirements', 'responsibilities', 'qualifications', 'bonus_points', 'benefits'),
|
|
'classes': ('collapse',)
|
|
}),
|
|
('Dates', {
|
|
'fields': ('start_date', 'deadline', 'posted_date', 'updated_date')
|
|
}),
|
|
)
|
|
|
|
def status_badge(self, obj):
|
|
colors = {
|
|
'active': 'green',
|
|
'closed': 'red',
|
|
'draft': 'orange'
|
|
}
|
|
return format_html(
|
|
'<span style="color: {}; font-weight: bold;">{}</span>',
|
|
colors.get(obj.status, 'black'),
|
|
obj.get_status_display()
|
|
)
|
|
status_badge.short_description = 'Status'
|
|
|
|
def applications_count(self, obj):
|
|
count = obj.applications.count()
|
|
return format_html(
|
|
'<span style="font-weight: bold;">{} application(s)</span>',
|
|
count
|
|
)
|
|
applications_count.short_description = 'Applications'
|
|
|
|
|
|
@admin.register(JobApplication)
|
|
class JobApplicationAdmin(admin.ModelAdmin):
|
|
list_display = [
|
|
'full_name',
|
|
'email',
|
|
'job',
|
|
'status_badge',
|
|
'applied_date',
|
|
'resume_link'
|
|
]
|
|
list_filter = ['status', 'job', 'applied_date']
|
|
search_fields = ['first_name', 'last_name', 'email', 'job__title']
|
|
readonly_fields = ['applied_date', 'updated_date', 'resume_link']
|
|
|
|
fieldsets = (
|
|
('Job Information', {
|
|
'fields': ('job', 'status')
|
|
}),
|
|
('Applicant Information', {
|
|
'fields': ('first_name', 'last_name', 'email', 'phone')
|
|
}),
|
|
('Professional Information', {
|
|
'fields': ('current_position', 'current_company', 'years_of_experience')
|
|
}),
|
|
('Application Details', {
|
|
'fields': ('cover_letter', 'resume', 'resume_link', 'portfolio_url')
|
|
}),
|
|
('Social Links', {
|
|
'fields': ('linkedin_url', 'github_url', 'website_url'),
|
|
'classes': ('collapse',)
|
|
}),
|
|
('Availability & Salary', {
|
|
'fields': ('available_from', 'notice_period', 'expected_salary', 'salary_currency'),
|
|
'classes': ('collapse',)
|
|
}),
|
|
('Metadata', {
|
|
'fields': ('applied_date', 'updated_date', 'consent', 'notes')
|
|
}),
|
|
)
|
|
|
|
def status_badge(self, obj):
|
|
colors = {
|
|
'new': 'blue',
|
|
'reviewing': 'orange',
|
|
'shortlisted': 'purple',
|
|
'interviewed': 'teal',
|
|
'accepted': 'green',
|
|
'rejected': 'red'
|
|
}
|
|
return format_html(
|
|
'<span style="color: {}; font-weight: bold;">{}</span>',
|
|
colors.get(obj.status, 'black'),
|
|
obj.get_status_display()
|
|
)
|
|
status_badge.short_description = 'Status'
|
|
|
|
def resume_link(self, obj):
|
|
if obj.resume:
|
|
return format_html(
|
|
'<a href="{}" target="_blank">Download Resume</a>',
|
|
obj.resume.url
|
|
)
|
|
return '-'
|
|
resume_link.short_description = 'Resume'
|
|
|
|
actions = ['mark_as_reviewing', 'mark_as_shortlisted', 'mark_as_rejected']
|
|
|
|
def mark_as_reviewing(self, request, queryset):
|
|
queryset.update(status='reviewing')
|
|
self.message_user(request, f'{queryset.count()} application(s) marked as reviewing.')
|
|
mark_as_reviewing.short_description = 'Mark as Reviewing'
|
|
|
|
def mark_as_shortlisted(self, request, queryset):
|
|
queryset.update(status='shortlisted')
|
|
self.message_user(request, f'{queryset.count()} application(s) marked as shortlisted.')
|
|
mark_as_shortlisted.short_description = 'Mark as Shortlisted'
|
|
|
|
def mark_as_rejected(self, request, queryset):
|
|
queryset.update(status='rejected')
|
|
self.message_user(request, f'{queryset.count()} application(s) marked as rejected.')
|
|
mark_as_rejected.short_description = 'Mark as Rejected'
|
|
|