fix(views): исправить bulk update и удалить неиспользуемый код

Критические исправления:
- actions.py: заменить bulk update() на save() для EmployeeDepartment
  Причина: bulk update НЕ вызывает Django signals!
  Было: .update(is_active=False) - сигнал не срабатывает
  Стало: for loop с save() - сигнал срабатывает для каждой записи

- _helpers.py: удалить неиспользуемую функцию _ldap_try()
  Нигде не используется после рефакторинга

- _helpers.py: удалить неиспользуемые импорты
  DirectoryLdapError, DirectoryServiceError, DirectoryDbError, status

- actions.py: обновить комментарий с правильным названием сигнала
  sync_department_member_to_ldap вместо устаревшего sync_member

Функционал сохранен: при увольнении сотрудника теперь корректно
срабатывают сигналы для каждого EmployeeDepartment, что приводит
к корректной синхронизации с LDAP (перемещение из OU отделов).
This commit is contained in:
lizerk 2026-03-18 18:28:11 +03:00
parent 51b878c32b
commit 5d729fa1f0
2 changed files with 11 additions and 25 deletions

View File

@ -7,10 +7,7 @@ import logging
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db.models import Q
from employees.ldap.errors import (DirectoryDbError, DirectoryLdapError,
DirectoryServiceError)
from employees.utils import _detect_phone_field
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
@ -23,25 +20,11 @@ PHONE_FIELD = _detect_phone_field()
def _is_ldap_enabled() -> bool:
"""Проверяет, включена ли интеграция с LDAP."""
return getattr(settings, "LDAP_ENABLED", False)
def _ldap_try(fn):
"""Выполняет функцию, которая работает с LDAP, и обрабатывает ошибки.
Если LDAP отключен, функция не выполняется и возвращается None.
"""Проверяет, включена ли интеграция с LDAP.
Используется только в RegisterAPIView для создания LDAP пользователей.
"""
if not _is_ldap_enabled():
return None
try:
fn()
return None
except (DirectoryLdapError, DirectoryServiceError, DirectoryDbError) as e:
return Response(
{"detail": f"LDAP sync failed: {e}"}, status=status.HTTP_502_BAD_GATEWAY
)
return getattr(settings, "LDAP_ENABLED", False)
class HistoryActionMixin:

View File

@ -82,7 +82,7 @@ class EmployeeActionViewSet(HistoryActionMixin, viewsets.ModelViewSet):
Работает только с БД. LDAP синхронизация через сигналы:
- sync_employee_to_ldap_on_save: активация/деактивация в LDAP
- sync_member (signals_department.py): удаление из отделов в LDAP
- sync_department_member_to_ldap: удаление из отделов в LDAP
"""
emp = action_obj.employee
@ -94,9 +94,12 @@ class EmployeeActionViewSet(HistoryActionMixin, viewsets.ModelViewSet):
emp.save(update_fields=["is_active"])
# Деактивируем связи с отделами (сигналы синхронизируют в LDAP)
EmployeeDepartment.objects.filter(employee=emp, is_active=True).update(
is_active=False, date_to=timezone.now().date()
)
# ВАЖНО: используем save() для каждой записи, чтобы сработали сигналы
today = timezone.now().date()
for emp_dept in EmployeeDepartment.objects.filter(employee=emp, is_active=True):
emp_dept.is_active = False
emp_dept.date_to = today
emp_dept.save(update_fields=["is_active", "date_to"])
else:
# Любое иное событие делает сотрудника активным (сигнал синхронизирует в LDAP)
if not emp.is_active: