diff --git a/backend/employees/admin.py b/backend/employees/admin.py index 330755d9..81ca5eaa 100644 --- a/backend/employees/admin.py +++ b/backend/employees/admin.py @@ -17,6 +17,7 @@ from .models import ( EmployeeDepartment, Position, Skill, + LdapSyncState, ) # ========================= @@ -278,3 +279,45 @@ class PermissionAdmin(admin.ModelAdmin): list_display = ("name", "codename", "content_type") list_filter = ("content_type",) search_fields = ("name", "codename") + + +@admin.register(LdapSyncState) +class LdapSyncStateAdmin(admin.ModelAdmin): + """Админка для просмотра состояния синхронизации LDAP.""" + + list_display = ( + "model", + "object_pk", + "ldap_dn_short", + "ldap_guid", + "last_sync_dir", + "updated_at", + ) + list_filter = ("model", "last_sync_dir") + search_fields = ("object_pk", "ldap_dn", "ldap_guid") + readonly_fields = ( + "model", + "object_pk", + "ldap_dn", + "ldap_guid", + "last_ldap_modify_ts", + "last_django_modify_ts", + "last_sync_dir", + "data_hash", + "updated_at", + ) + + def ldap_dn_short(self, obj): + """Показываем сокращенную версию DN для удобства.""" + if obj.ldap_dn: + return obj.ldap_dn[:50] + "..." if len(obj.ldap_dn) > 50 else obj.ldap_dn + return "-" + ldap_dn_short.short_description = "LDAP DN" + + def has_add_permission(self, request): + """Запрещаем создание вручную.""" + return False + + def has_delete_permission(self, request, obj=None): + """Разрешаем удаление для очистки.""" + return True diff --git a/backend/employees/views_front.py b/backend/employees/views_front.py index a4ed6588..9ba927a4 100644 --- a/backend/employees/views_front.py +++ b/backend/employees/views_front.py @@ -546,58 +546,8 @@ def employee_edit(request, pk: int): except Exception: data = {"detail": resp.text} - accepts = (request.headers.get("Accept") or "").lower() - is_ajax = request.headers.get("X-Requested-With") == "XMLHttpRequest" - wants_json = "application/json" in accepts or is_ajax - - if wants_json: - return JsonResponse(data or {}, status=resp.status) - - if resp.ok: - messages.success(request, "Профиль сотрудника обновлён") - redirect_url = request.META.get("HTTP_REFERER") or reverse( - "employees:employee_profile", - args=(pk,), - ) - return redirect(redirect_url) - else: - # При ошибке валидации показываем детали - if resp.status == 400 and isinstance(data, dict): - # Собираем все ошибки валидации - error_messages = [] - for field, errors in data.items(): - if field == 'detail': - error_messages.append(str(errors)) - elif isinstance(errors, list): - field_name = field.replace('_', ' ').title() - for error in errors: - if isinstance(error, dict): - err_str = error.get('string', error) - error_messages.append(f"{field_name}: {err_str}") - else: - error_messages.append(f"{field_name}: {error}") - else: - field_name = field.replace('_', ' ').title() - error_messages.append(f"{field_name}: {errors}") - - if error_messages: - for msg in error_messages: - messages.error(request, msg) - else: - messages.error(request, "Ошибка валидации данных") - else: - detail = "" - if isinstance(data, dict): - detail = data.get("detail") or data.get("error") or "" - error_msg = ( - detail - or f"Не удалось обновить сотрудника (HTTP {resp.status})" - ) - messages.error(request, error_msg) - - # Возвращаем на страницу профиля сотрудника - profile_url = reverse("employees:employee_detail", args=(pk,)) - return redirect(profile_url) + # Всегда возвращаем JSON без редиректа + return JsonResponse(data or {}, status=resp.status) # ---------- EDIT ME ---------- @@ -692,57 +642,8 @@ def employee_edit_me(request): except Exception: data = {"detail": resp.text} - accepts = (request.headers.get("Accept") or "").lower() - is_ajax = request.headers.get("X-Requested-With") == "XMLHttpRequest" - wants_json = "application/json" in accepts or is_ajax - - if wants_json: - return JsonResponse(data or {}, status=resp.status) - - if resp.ok: - messages.success(request, "Профиль обновлён") - redirect_url = ( - request.META.get("HTTP_REFERER") - or reverse("employees:profile") - ) - return redirect(redirect_url) - else: - # При ошибке валидации показываем детали - if resp.status == 400 and isinstance(data, dict): - # Собираем все ошибки валидации - error_messages = [] - for field, errors in data.items(): - if field == 'detail': - error_messages.append(str(errors)) - elif isinstance(errors, list): - field_name = field.replace('_', ' ').title() - for error in errors: - if isinstance(error, dict): - err_str = error.get('string', error) - error_messages.append(f"{field_name}: {err_str}") - else: - error_messages.append(f"{field_name}: {error}") - else: - field_name = field.replace('_', ' ').title() - error_messages.append(f"{field_name}: {errors}") - - if error_messages: - for msg in error_messages: - messages.error(request, msg) - else: - messages.error(request, "Ошибка валидации данных") - else: - detail = "" - if isinstance(data, dict): - detail = data.get("detail") or data.get("error") or "" - error_msg = ( - detail or f"Не удалось обновить профиль (HTTP {resp.status})" - ) - messages.error(request, error_msg) - - # Возвращаем на страницу профиля (где есть форма редактирования) - profile_url = reverse("employees:profile") - return redirect(profile_url) + # Всегда возвращаем JSON без редиректа + return JsonResponse(data or {}, status=resp.status) # ---------- CREATE (staff) ----------