Files
Django/jituan/services/admin_assignments.py
2026-07-29 06:53:06 +08:00

193 lines
5.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""admin_assignment 任职 CRUD。
集团任职用 club_id=''(禁止 NULLMySQL 对 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)