"""rank.views.kaohe_jilu - auto-generated by split script.""" import json import logging from decimal import Decimal from django.db import models, transaction from django.db.models import F from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated from ..utils import get_tag_fee, create_shenhe_jilu, validate_shenheguan from ..models import ( YonghuChenghao, Chenghao, KaoheCishuFeiyong, KaoheJujueJilu, KaoheguanBankuai, Bankuai, ShenheJilu, KaoheJiluFeiyong ) from users.models import UserShenheguan, UserDashou from users.business_models import User from products.models import ShangpinLeixing logger = logging.getLogger(__name__) class KaoheJiluView(APIView): """获取打手本人的考核记录(支持筛选状态)""" permission_classes = [IsAuthenticated] def post(self, request): try: user = request.user status = request.data.get('status', 'pending') # pending / passed page = int(request.data.get('page', 1)) page_size = int(request.data.get('page_size', 5)) if status == 'pending': # 进行中/未通过:审核中(0)、待审核(3)、未通过(2) query = ShenheJilu.objects.filter( shenqingren_id=user.UserUID, zhuangtai__in=[0, 2, 3] ) else: query = ShenheJilu.objects.filter( shenqingren_id=user.UserUID, zhuangtai=1 # 已通过 ) total = query.count() records = query.order_by('-CreateTime')[(page-1)*page_size : page*page_size] # 批量预取关联数据,避免循环内 N+1 records = records.select_related('chenghao', 'bankuai') records_list = list(records) jilu_ids = [jl.jilu_id for jl in records_list] # 批量汇总缴纳总额(按 jilu_id 分组聚合) _fee_map = {} if jilu_ids: _fee_agg = KaoheJiluFeiyong.objects.filter( jilu_id__in=jilu_ids ).values('jilu_id').annotate(total=models.Sum('jine')) for item in _fee_agg: _fee_map[item['jilu_id']] = float(item['total'] or 0.00) # 批量获取上次拒绝原因(每个 jilu_id 取最近一条) _fail_map = {} if jilu_ids: _reject_qs = KaoheJujueJilu.objects.filter( jilu_id__in=jilu_ids ).order_by('jilu_id', '-CreateTime') for rej in _reject_qs: if rej.jilu_id not in _fail_map: # 只取首条(最近) _fail_map[rej.jilu_id] = rej.yuanyin or '' # 批量获取考核官头像 _avatar_map = {} _kg_ids = {jl.shenheguan_id for jl in records_list if jl.shenheguan_id} if _kg_ids: for u in User.objects.filter(UserUID__in=_kg_ids): _avatar_map[u.UserUID] = u.Avatar or '' data = [] for jl in records_list: total_fee = _fee_map.get(jl.jilu_id, 0.00) fail_reason = _fail_map.get(jl.jilu_id, '') kg_avatar = _avatar_map.get(jl.shenheguan_id, '') data.append({ 'jilu_id': jl.jilu_id, 'chenghao_name': jl.chenghao.mingcheng if jl.chenghao else '', 'bankuai_name': jl.bankuai.mingcheng if jl.bankuai else '', 'zhuangtai': jl.zhuangtai, 'statusText': dict(ShenheJilu._meta.get_field('zhuangtai').choices).get(jl.zhuangtai, '未知'), 'statusColor': {0: '#FFA500', 1: '#27ae60', 2: '#e74c3c', 3: '#3498db'}.get(jl.zhuangtai, '#888'), 'shenheguan_id': jl.shenheguan_id, 'shenheguan_avatar': kg_avatar, 'dashou_youxi_id': jl.dashou_youxi_id, 'dashou_beizhu': jl.dashou_beizhu, 'cishu': jl.cishu, 'total_fee': float(total_fee), 'last_fail_reason': fail_reason, 'CreateTime': jl.CreateTime.strftime('%Y-%m-%d %H:%M:%S'), # 为再次申请预留标签对象数据(前端可能用到) 'tag_obj': { 'id': jl.chenghao_id, 'name': jl.chenghao.mingcheng if jl.chenghao else '', # 其他字段按需,但申请时会重新拉取 } if jl.chenghao else None, }) has_more = (page * page_size) < total return Response({ 'code': 0, 'data': {'list': data, 'has_more': has_more, 'total': total} }) except Exception as e: return Response({'code': 500, 'msg': str(e)}, status=500) class KaoheJiluListView(APIView): """ 获取当前考核官的历史审核记录 路径:POST /dengji/khghqkhjl 权限:JWT Token (考核官) 参数: bankuai_id : int (可选,0或空表示全部) status : int (可选,0-全部 1-审核中 2-已通过 3-未通过) page : int (默认1) page_size : int (默认5) 返回: list, has_more, total """ permission_classes = [IsAuthenticated] def post(self, request): try: yonghu = request.user # 1. 验证考核官身份及账号状态 kg = UserShenheguan.objects.filter(user=yonghu, zhuangtai=1).first() if not kg: return Response({'code': 403, 'msg': '您不是考核官或账号异常'}) # 2. 获取参数 bankuai_id = request.data.get('bankuai_id') status = int(request.data.get('status', 0)) # 0全部 1审核中 2已通过 3未通过 page = int(request.data.get('page', 1)) page_size = int(request.data.get('page_size', 5)) # 3. 构建查询条件:只查当前考核官审核的记录 base_query = ShenheJilu.objects.filter(shenheguan_id=yonghu.UserUID) # 板块筛选 if bankuai_id and int(bankuai_id) > 0: base_query = base_query.filter(bankuai_id=int(bankuai_id)) # 状态筛选(前端传的状态映射到后端zhuangtai字段) status_map = { 0: None, # 全部不筛选 1: 0, # 审核中 2: 1, # 已通过 3: 2, # 未通过 } if status_map.get(status) is not None: base_query = base_query.filter(zhuangtai=status_map[status]) # 4. 计数与分页 total = base_query.count() offset = (page - 1) * page_size jilu_list = base_query.order_by('-CreateTime')[offset:offset + page_size] # 5. 预取关联数据,减少查询次数 jilu_list = jilu_list.select_related('bankuai', 'chenghao') # 为每条记录预取费用明细和拒绝记录(通过 related_name 或手动过滤) # 由于 KaoheJiluFeiyong 和 KaoheJujueJilu 通过外键指向 ShenheJilu (to_field='jilu_id'), # 可以使用 prefetch_related jilu_ids = [j.jilu_id for j in jilu_list] fee_dict = {} reject_dict = {} if jilu_ids: # 批量获取所有费用明细 fee_qs = KaoheJiluFeiyong.objects.filter(jilu_id__in=jilu_ids).order_by('cishu') for fee in fee_qs: if fee.jilu_id not in fee_dict: fee_dict[fee.jilu_id] = [] fee_dict[fee.jilu_id].append({'cishu': fee.cishu, 'jine': float(fee.jine)}) # 批量获取所有拒绝记录 reject_qs = KaoheJujueJilu.objects.filter(jilu_id__in=jilu_ids).order_by('cishu') for rej in reject_qs: if rej.jilu_id not in reject_dict: reject_dict[rej.jilu_id] = [] reject_dict[rej.jilu_id].append({ 'cishu': rej.cishu, 'yuanyin': rej.yuanyin, 'CreateTime': rej.CreateTime.strftime('%Y-%m-%d %H:%M:%S') if rej.CreateTime else '' }) # 6. 批量获取申请人信息(昵称和头像) applicant_ids = {j.shenqingren_id for j in jilu_list} user_map = {} if applicant_ids: users = User.objects.filter(UserUID__in=applicant_ids).select_related('DashouProfile') for u in users: avatar = u.Avatar or '' nicheng = '' try: # 打手扩展表可能有 nicheng nicheng = u.DashouProfile.nicheng if getattr(u, 'DashouProfile', None) else '' except UserDashou.DoesNotExist: pass user_map[u.UserUID] = { 'avatar': avatar, 'nicheng': nicheng or f'用户{u.UserUID}' } # 7. 组装数据 records = [] for jl in jilu_list: user_info = user_map.get(jl.shenqingren_id, {'avatar': '', 'nicheng': '未知'}) # 标签特效JSON texiao_json = {} if jl.chenghao and jl.chenghao.texiao_miaoshu: try: texiao_json = json.loads(jl.chenghao.texiao_miaoshu) except: pass # 汇总总缴纳费用 fee_items = fee_dict.get(jl.jilu_id, []) total_fee = sum(item['jine'] for item in fee_items) records.append({ 'jilu_id': jl.jilu_id, 'shenqingren_id': jl.shenqingren_id, 'shenqingren_avatar': user_info['avatar'], 'shenqingren_nicheng': user_info['nicheng'], 'bankuai_mingcheng': jl.bankuai.mingcheng if jl.bankuai else '', 'chenghao_mingcheng': jl.chenghao.mingcheng if jl.chenghao else '', 'chenghao_texiao_json': texiao_json, 'zhuangtai': jl.zhuangtai, # 0审核中 1通过 2未通过 3待审核 'cishu': jl.cishu, 'total_fee': total_fee, 'dashou_youxi_id': jl.dashou_youxi_id or '', 'dashou_beizhu': jl.dashou_beizhu or '', 'shenheguan_youxi_id': jl.shenheguan_youxi_id or '', 'guize_neirong': jl.guize_neirong or '', 'CreateTime': jl.CreateTime.strftime('%Y-%m-%d %H:%M:%S') if jl.CreateTime else '', 'UpdateTime': jl.UpdateTime.strftime('%Y-%m-%d %H:%M:%S') if jl.UpdateTime else '', 'fee_list': fee_items, 'reject_list': reject_dict.get(jl.jilu_id, []), }) has_more = (page * page_size) < total return Response({ 'code': 0, 'data': { 'list': records, 'has_more': has_more, 'total': total } }) except Exception as e: logger.error(f"获取考核记录异常: {str(e)}", exc_info=True) return Response({'code': 500, 'msg': '服务器内部错误'}, status=500)