"""admin_assignment 任职 CRUD(修复停用不生效、重复插入、IsSuperuser 绕过)。""" 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 _club_filter(qs, club_id): if club_id is None or club_id == '': return qs.filter(Q(club_id__isnull=True) | Q(club_id='')) return qs.filter(club_id=club_id) 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 create_or_reactivate_assignment( yonghuid, club_id, role_code, data_scope, is_primary, granted_by, ): active = find_active_assignment(yonghuid, club_id, role_code) if active: return None, '该任职记录已存在且有效' if is_primary: _clear_other_primary(yonghuid) inactive_qs = _club_filter( AdminAssignment.objects.filter(yonghuid=yonghuid, role_code=role_code).exclude(status=1), club_id, ).order_by('-id') inactive = inactive_qs.first() if inactive: if is_primary: _clear_other_primary(yonghuid) inactive_qs.exclude(pk=inactive.pk).update(status=0, UpdateTime=timezone.now()) AdminAssignment.objects.filter(pk=inactive.id).update( status=1, data_scope=data_scope, is_primary=is_primary, granted_by=granted_by, UpdateTime=timezone.now(), ) return inactive.id, None row = AdminAssignment.query.create( yonghuid=yonghuid, club_id=club_id, role_code=role_code, data_scope=data_scope, is_primary=is_primary, granted_by=granted_by, status=1, ) return row.id, None def _strip_system_super_if_needed(yonghuid): """ 停用集团权限后:非白名单账号必须摘掉 IsSuperuser。 否则 build_admin_club_context 仍把 is_group_admin=True,停用等于没停。 """ 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: user.IsSuperuser = False user.save(update_fields=['IsSuperuser']) def deactivate_all_group_assignments_for_user(yonghuid): """停用该用户全部集团级任职(空俱乐部 / ALL_CLUBS / GROUP_* 角色)。""" yonghuid = (yonghuid or '').strip() if not yonghuid: return 0 qs = AdminAssignment.objects.filter(yonghuid=yonghuid, status=1).filter( Q(club_id__isnull=True) | Q(club_id='') | Q(data_scope=DATA_SCOPE_ALL) | Q(role_code__in=list(GROUP_ROLE_CODES)) ) return qs.update(status=0, UpdateTime=timezone.now()) def deactivate_assignment(assignment_id): """ 停用任职。 - 同人同角色同俱乐部(含 NULL 重复行)全部停 - 若是集团级任职:再停掉该人全部集团任职,并摘掉非白名单 IsSuperuser """ try: pk = int(assignment_id) except (TypeError, ValueError): return False, '任职 id 无效' row = AdminAssignment.objects.filter(pk=pk).first() if not row: return False, '任职记录不存在' qs = AdminAssignment.objects.filter( yonghuid=row.yonghuid, role_code=row.role_code, status=1, ) qs = _club_filter(qs, row.club_id) qs.update(status=0, UpdateTime=timezone.now()) is_group_level = ( not (row.club_id or '').strip() or (row.data_scope or '') == DATA_SCOPE_ALL or (row.role_code or '') in GROUP_ROLE_CODES ) if is_group_level: deactivate_all_group_assignments_for_user(row.yonghuid) _strip_system_super_if_needed(row.yonghuid) return True, None def deactivate_all_assignments_for_user(yonghuid): """账号禁用时:停用该用户全部有效任职,并摘掉非白名单 IsSuperuser。""" yonghuid = (yonghuid or '').strip() if not yonghuid: return 0 n = AdminAssignment.objects.filter(yonghuid=yonghuid, status=1).update( status=0, UpdateTime=timezone.now(), ) _strip_system_super_if_needed(yonghuid) return n def dedupe_active_assignments(): """停用重复的有效任职,每组 (yonghuid, club_id, role_code) 只保留一条。""" rows = list( AdminAssignment.query.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).update( status=0, UpdateTime=timezone.now(), ) return len(dup_ids)