👥 Добавлено управление персоналом и карьерой
✨ Новые функции: - 🧑💻 Team модель для управления сотрудниками • Полная информация о персонале (имя, должность, отдел) • Фотографии и контактные данные • Социальные сети (LinkedIn, GitHub, Telegram) • Навыки и опыт работы • Гибкие настройки отображения - 💼 Career модель для вакансий • Детальное описание позиций • Требования и обязанности • Зарплатные вилки • Типы занятости и уровни опыта • Статусы вакансий и дедлайны 🔧 Админ-панель: - Удобные интерфейсы для HR-менеджмента - Группировка полей и фильтрация - Быстрые действия для массовых операций - Сортировка по приоритету 📊 База данных: - Миграция 0013_career_team.py - Оптимизированные индексы и связи
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
from django.contrib import admin
|
||||
from .models import Service, Project, Client, Order, Review, BlogPost, Category, ServiceRequest, HeroBanner, ContactInfo
|
||||
from .models import Service, Project, Client, Order, Review, BlogPost, Category, ServiceRequest, HeroBanner, ContactInfo, Team, Career
|
||||
from .forms import ProjectForm
|
||||
|
||||
@admin.register(ContactInfo)
|
||||
@@ -87,4 +87,96 @@ class CategoryAdmin(admin.ModelAdmin):
|
||||
class ServiceRequestAdmin(admin.ModelAdmin):
|
||||
list_display = ('service','token', 'client', 'created_at')
|
||||
search_fields = ('service','token', 'client')
|
||||
list_filter = ('service','token','client')
|
||||
list_filter = ('service','token','client')
|
||||
|
||||
|
||||
@admin.register(Team)
|
||||
class TeamAdmin(admin.ModelAdmin):
|
||||
list_display = ('first_name', 'last_name', 'position', 'department', 'is_active', 'display_order')
|
||||
list_filter = ('department', 'is_active', 'show_on_about')
|
||||
search_fields = ('first_name', 'last_name', 'position', 'skills')
|
||||
list_editable = ('display_order', 'is_active')
|
||||
|
||||
fieldsets = (
|
||||
('Основная информация', {
|
||||
'fields': ('first_name', 'last_name', 'position', 'department')
|
||||
}),
|
||||
('Контактные данные', {
|
||||
'fields': ('email', 'phone', 'photo'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
('Профессиональная информация', {
|
||||
'fields': ('bio', 'skills', 'experience_years')
|
||||
}),
|
||||
('Социальные сети', {
|
||||
'fields': ('linkedin', 'github', 'telegram'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
('Настройки отображения', {
|
||||
'fields': ('is_active', 'show_on_about', 'display_order')
|
||||
}),
|
||||
)
|
||||
|
||||
def get_queryset(self, request):
|
||||
return super().get_queryset(request).order_by('display_order', 'last_name')
|
||||
|
||||
|
||||
@admin.register(Career)
|
||||
class CareerAdmin(admin.ModelAdmin):
|
||||
list_display = ('title', 'department', 'experience_level', 'employment_type', 'status', 'is_featured', 'created_at')
|
||||
list_filter = ('status', 'employment_type', 'experience_level', 'department', 'is_featured')
|
||||
search_fields = ('title', 'department', 'description', 'required_skills')
|
||||
list_editable = ('status', 'is_featured')
|
||||
|
||||
fieldsets = (
|
||||
('Основная информация', {
|
||||
'fields': ('title', 'department', 'location', 'employment_type', 'experience_level')
|
||||
}),
|
||||
('Описание вакансии', {
|
||||
'fields': ('description', 'responsibilities', 'requirements', 'benefits')
|
||||
}),
|
||||
('Зарплата', {
|
||||
'fields': ('salary_min', 'salary_max', 'salary_currency'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
('Навыки', {
|
||||
'fields': ('required_skills', 'preferred_skills'),
|
||||
}),
|
||||
('Контактная информация', {
|
||||
'fields': ('contact_email', 'contact_person'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
('Статус и метаданные', {
|
||||
'fields': ('status', 'is_featured', 'application_deadline', 'published_at')
|
||||
}),
|
||||
)
|
||||
|
||||
readonly_fields = ('created_at', 'updated_at')
|
||||
|
||||
def get_queryset(self, request):
|
||||
return super().get_queryset(request).order_by('-is_featured', '-created_at')
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
if obj.status == 'active' and not obj.published_at:
|
||||
from django.utils import timezone
|
||||
obj.published_at = timezone.now()
|
||||
super().save_model(request, obj, form, change)
|
||||
|
||||
actions = ['mark_as_active', 'mark_as_paused', 'mark_as_closed']
|
||||
|
||||
def mark_as_active(self, request, queryset):
|
||||
from django.utils import timezone
|
||||
updated = queryset.update(status='active')
|
||||
queryset.filter(published_at__isnull=True).update(published_at=timezone.now())
|
||||
self.message_user(request, f'{updated} вакансий отмечены как активные.')
|
||||
mark_as_active.short_description = "Отметить как активные"
|
||||
|
||||
def mark_as_paused(self, request, queryset):
|
||||
updated = queryset.update(status='paused')
|
||||
self.message_user(request, f'{updated} вакансий приостановлены.')
|
||||
mark_as_paused.short_description = "Приостановить"
|
||||
|
||||
def mark_as_closed(self, request, queryset):
|
||||
updated = queryset.update(status='closed')
|
||||
self.message_user(request, f'{updated} вакансий закрыты.')
|
||||
mark_as_closed.short_description = "Закрыть"
|
||||
Reference in New Issue
Block a user