"""admin_assignment 任职 CRUD。 集团任职用 club_id=''(禁止 NULL):MySQL 对 NULL 唯一约束失效,会无限复制, 导致「停一条冒出五六条」。停用改为硬删除。 """ from django.db.models import Q from django.utils import timezone from jituan.constants import DATA_SCOPE_ALL, DATA_SCOPE_SINGLE, SUPER_ADMIN_PHONES from jituan.models import AdminAssignment GROUP_ROLE_CODES = frozenset({ 'GROUP_OWNER', 'GROUP_SUPER_ADMIN', 'GROUP_AFTER_SALES', 'GROUP_FINANCE', 'GROUP_CONFIG', }) def normalize_club_id(club_id): """集团级统一成空串,禁止 NULL(避免唯一索引失效)。""" if club_id is None: return '' s = str(club_id).strip() return s def _club_filter(qs, club_id): cid = normalize_club_id(club_id) if not cid: return qs.filter(Q(club_id__isnull=True) | Q(club_id='')) return qs.filter(club_id=cid) def find_assignment(yonghuid, club_id, role_code): qs = AdminAssignment.query.filter(yonghuid=yonghuid, role_code=role_code) return _club_filter(qs, club_id).order_by('-id').first() def find_active_assignment(yonghuid, club_id, role_code): qs = AdminAssignment.query.filter(yonghuid=yonghuid, role_code=role_code, status=1) return _club_filter(qs, club_id).order_by('-id').first() def clear_other_primary_assignments(yonghuid, except_id=None): qs = AdminAssignment.query.filter(yonghuid=yonghuid, status=1, is_primary=True) if except_id: qs = qs.exclude(id=except_id) ids = list(qs.values_list('id', flat=True)) if ids: AdminAssignment.objects.filter(pk__in=ids).update( is_primary=False, UpdateTime=timezone.now(), ) def _clear_other_primary(yonghuid, except_id=None): clear_other_primary_assignments(yonghuid, except_id=except_id) def _strip_system_super_if_needed(yonghuid): yonghuid = (yonghuid or '').strip() if not yonghuid: return try: from users.business_models import User except Exception: return user = User.objects.filter(UserUID=yonghuid).first() if not user: return if (user.Phone or '') in SUPER_ADMIN_PHONES: return if user.IsSuperuser or user.IsStaff: user.IsSuperuser = False user.IsStaff = False user.save(update_fields=['IsSuperuser', 'IsStaff']) def create_or_reactivate_assignment( yonghuid, club_id, role_code, data_scope, is_primary, granted_by, ): club_id = normalize_club_id(club_id) if not club_id: data_scope = DATA_SCOPE_ALL # 创建前先清同键垃圾(含 NULL/空串/status=0 重复) junk = _club_filter( AdminAssignment.objects.filter(yonghuid=yonghuid, role_code=role_code), club_id, ) active = junk.filter(status=1).order_by('-id') if active.exists(): keep = active.first() junk.exclude(pk=keep.pk).delete() return None, '该任职记录已存在且有效' junk.delete() if is_primary: _clear_other_primary(yonghuid) row = AdminAssignment.objects.create( yonghuid=yonghuid, club_id=club_id, role_code=role_code, data_scope=data_scope, is_primary=is_primary, granted_by=granted_by or '', status=1, ) return row.id, None def _is_group_level(row): return ( not normalize_club_id(row.club_id) or (row.data_scope or '') == DATA_SCOPE_ALL or (row.role_code or '') in GROUP_ROLE_CODES ) def deactivate_assignment(assignment_id): """停用=硬删除。集团级则删光该人全部集团任职并摘 IsSuperuser。""" try: pk = int(assignment_id) except (TypeError, ValueError): return False, '任职 id 无效' row = AdminAssignment.objects.filter(pk=pk).first() if not row: # 可能已被删,幂等成功 return True, None yonghuid = row.yonghuid role_code = row.role_code club_id = row.club_id group_level = _is_group_level(row) # 同人同角色同俱乐部(含 NULL/'')全部硬删 _club_filter( AdminAssignment.objects.filter(yonghuid=yonghuid, role_code=role_code), club_id, ).delete() if group_level: AdminAssignment.objects.filter(yonghuid=yonghuid).filter( Q(club_id__isnull=True) | Q(club_id='') | Q(data_scope=DATA_SCOPE_ALL) | Q(role_code__in=list(GROUP_ROLE_CODES)) ).delete() _strip_system_super_if_needed(yonghuid) return True, None def deactivate_all_assignments_for_user(yonghuid): """账号禁用:硬删全部任职 + 摘超管。""" yonghuid = (yonghuid or '').strip() if not yonghuid: return 0 deleted, _ = AdminAssignment.objects.filter(yonghuid=yonghuid).delete() _strip_system_super_if_needed(yonghuid) return deleted def dedupe_active_assignments(): """硬删重复任职;并把 club_id=NULL 归一成 ''。""" # 归一 NULL -> '' AdminAssignment.objects.filter(club_id__isnull=True).update(club_id='') rows = list( AdminAssignment.objects.filter(status=1).order_by('yonghuid', 'club_id', 'role_code', 'id') ) seen = {} dup_ids = [] for row in rows: key = (row.yonghuid, row.club_id or '', row.role_code) if key in seen: dup_ids.append(row.id) else: seen[key] = row.id if dup_ids: AdminAssignment.objects.filter(pk__in=dup_ids).delete() return len(dup_ids)