尝试将 backend 做了视图拆分,来保证可维护性,若此版本存在生产环境问题应该回退
This commit is contained in:
354
backend/views/sections.py
Normal file
354
backend/views/sections.py
Normal file
@@ -0,0 +1,354 @@
|
||||
import hmac
|
||||
import threading
|
||||
import traceback
|
||||
import uuid
|
||||
import hashlib
|
||||
import xmltodict
|
||||
import time
|
||||
import logging
|
||||
import requests
|
||||
import os
|
||||
import secrets
|
||||
import random
|
||||
import string
|
||||
from calendar import monthrange
|
||||
from decimal import Decimal
|
||||
from datetime import date, datetime, timedelta
|
||||
from django.utils import timezone
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.core.paginator import Paginator
|
||||
from django.db import models, transaction, IntegrityError
|
||||
from django.db.models import Q, Count, Sum, F, Exists, OuterRef
|
||||
from gvsdsdk.fluent import db, func, FQ
|
||||
from django.db.models.functions import TruncDate, TruncMonth, TruncYear
|
||||
from django.contrib.auth.hashers import make_password
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||||
from rest_framework.parsers import JSONParser, MultiPartParser, FormParser
|
||||
|
||||
# 工具类导入
|
||||
from utils.oss_utils import validate_image, upload_to_oss, delete_from_oss
|
||||
from backend.utils import (
|
||||
update_dashou_daily_by_action,
|
||||
update_shangjia_daily
|
||||
)
|
||||
from jituan.services.club_context import filter_club_char_field, filter_queryset_by_club, filter_user_related_by_club, filter_user_qs_by_club, orders_for_request
|
||||
from jituan.services.catalog_scope import block_non_group_catalog_scope
|
||||
from jituan.services.club_penalty import (
|
||||
filter_penalty_qs, resolve_penalty_club_id, filter_gsfenhong_qs,
|
||||
forbid_penalty_out_of_scope, resolve_penalty_record_club_id,
|
||||
)
|
||||
from jituan.services.club_user_access import forbid_if_user_out_of_scope, list_response_meta
|
||||
from shop.utils import update_dianpu_daily_stat
|
||||
from products.utils import update_shangpin_daily_stat
|
||||
from orders.notice_tasks import dingdan_guangbo
|
||||
from ..utils import (
|
||||
verify_kefu_permission,
|
||||
PERMISSION_TO_SHENFEN,
|
||||
SHENFEN_PROFILE_MAP,
|
||||
has_fadan_view_permission,
|
||||
has_merchant_order_permission,
|
||||
check_fadan_permission,
|
||||
pick_order_id,
|
||||
pick_penalty_create_params,
|
||||
write_xiugai_log,
|
||||
XIUGAI_LEIXING_DASHOU,
|
||||
XIUGAI_LEIXING_GUANSHI,
|
||||
XIUGAI_LEIXING_SHANGJIA,
|
||||
XIUGAI_LEIXING_ZUZHANG,
|
||||
XIUGAI_LEIXING_LABEL,
|
||||
)
|
||||
|
||||
# models 集中导入
|
||||
## gvsdsdk RBAC 模型(使用 PascalCase 字段名,匹配实际数据库表结构)
|
||||
from gvsdsdk.models import Role, Permission, RolePermission, UserRole
|
||||
## backend
|
||||
from backend.models import WithdrawalDailyStats
|
||||
|
||||
## users
|
||||
from users.models import (
|
||||
UserGuanshi, UserBoss, UserZuzhang,
|
||||
UserKefu, UserDashou, Xiugaijilu, UserShangjia, UserShenheguan
|
||||
)
|
||||
from users.business_models import User
|
||||
|
||||
## orders
|
||||
from orders.models import (
|
||||
CommissionRate, PlayerDeliveryImage, PenaltyRecord,
|
||||
OrderPlayerHistory, Order, RefundRecord,
|
||||
MerchantOrderExt, Penalty, PenaltyAppealImage, PenaltyBonus
|
||||
)
|
||||
|
||||
## shop
|
||||
from shop.models import Dianpu, DianpuMorenPeizhi, YonghuPingzheng, ShangpinLeixingDianpu, DianpuShangpinShenheShezhi
|
||||
|
||||
## products
|
||||
from products.models import (
|
||||
Shangpin, ShangpinLeixing, ShangpinZhuanqu, Huiyuan,
|
||||
DuociFenhong, Czjilu, Huiyuangoumai, Gsfenhong
|
||||
)
|
||||
|
||||
## config
|
||||
from config.models import (
|
||||
WithdrawConfig, ShangjiaLianjie, AccountPermission,
|
||||
TixianQuotaDefault,
|
||||
DailyIncomeStat, DailyPayoutStat, PopupPage, PopupConfig, PopupImage
|
||||
)
|
||||
|
||||
## rank
|
||||
from rank.models import (
|
||||
KaoheguanBankuai, Bankuai, Chenghao, KaoheCishuFeiyong,
|
||||
YonghuChenghao, ShenheJilu, KaoheJiluFeiyong, KaoheJujueJilu
|
||||
)
|
||||
|
||||
# 序列化器
|
||||
from ..serializers import PopupPageSerializer
|
||||
|
||||
# 全局常量、日志对象
|
||||
logger = logging.getLogger('houtai')
|
||||
SHOP_PRODUCT_PERMS = ['1199ab', '1199abc', '1199abd']
|
||||
|
||||
class HqbkxxView(APIView):
|
||||
"""
|
||||
获取板块配置所需全部数据
|
||||
POST /houtai/hqbkxx
|
||||
Body: { "phone": "管理员手机号" }
|
||||
"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def post(self, request):
|
||||
# 1. 从前端获取传递的账号,用于防越权校验
|
||||
username_from_frontend = request.data.get('phone', None)
|
||||
|
||||
# 2. 调用公共验证方法
|
||||
kefu_obj, permissions = verify_kefu_permission(request, username_from_frontend)
|
||||
|
||||
# 3. 如果第一个返回值为 None,说明验证失败,直接返回第二个值
|
||||
if kefu_obj is None:
|
||||
return permissions
|
||||
|
||||
# ---------- 验证通过 ----------
|
||||
# 4. 检查是否有板块管理权限
|
||||
if 'bankuai' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无板块管理权限'}, status=403)
|
||||
scope_err = block_non_group_catalog_scope(request)
|
||||
if scope_err:
|
||||
return Response({'code': 400, 'msg': scope_err})
|
||||
|
||||
# 5. 查询所有板块
|
||||
bankuai_list = []
|
||||
for bk in Bankuai.query.all():
|
||||
bankuai_list.append({
|
||||
'bankuai_id': bk.bankuai_id,
|
||||
'mingcheng': bk.mingcheng,
|
||||
'CreateTime': bk.CreateTime.strftime('%Y-%m-%d %H:%M:%S') if bk.CreateTime else ''
|
||||
})
|
||||
|
||||
# 6. 查询所有商品类型
|
||||
shangpin_leixing_list = []
|
||||
for sp in ShangpinLeixing.query.all():
|
||||
shangpin_leixing_list.append({
|
||||
'id': sp.id,
|
||||
'jieshao': sp.jieshao,
|
||||
'tupian_url': sp.tupian_url or '',
|
||||
'bankuai_id': sp.bankuai_id
|
||||
})
|
||||
|
||||
# 7. 查询会员(附带当前俱乐部售价)
|
||||
from jituan.constants import CLUB_ID_DEFAULT, DATA_SCOPE_ALL
|
||||
from jituan.models import ClubHuiyuanPrice
|
||||
from jituan.services.club_context import resolve_club_id_from_request, resolve_club_scope
|
||||
|
||||
scope = resolve_club_scope(request)
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
price_map = {}
|
||||
if scope != DATA_SCOPE_ALL:
|
||||
for row in ClubHuiyuanPrice.query.filter(club_id=club_id):
|
||||
price_map[row.huiyuan_id] = row
|
||||
|
||||
huiyuan_list = []
|
||||
for hy in Huiyuan.query.all():
|
||||
row = price_map.get(hy.huiyuan_id)
|
||||
if scope != DATA_SCOPE_ALL and club_id != CLUB_ID_DEFAULT and row is None:
|
||||
continue
|
||||
if row is not None and not row.is_enabled:
|
||||
continue
|
||||
item = {
|
||||
'huiyuan_id': hy.huiyuan_id,
|
||||
'jieshao': hy.jieshao,
|
||||
'bankuai_id': hy.bankuai_id,
|
||||
'jiage': str(row.jiage) if row else str(hy.jiage),
|
||||
'guanshifc': str(row.guanshifc) if row else str(hy.guanshifc),
|
||||
'zuzhangfc': str(row.zuzhangfc) if row else str(hy.zuzhangfc),
|
||||
}
|
||||
huiyuan_list.append(item)
|
||||
|
||||
return Response({
|
||||
'code': 0,
|
||||
'msg': 'ok',
|
||||
'data': {
|
||||
'bankuai': bankuai_list,
|
||||
'shangpin_leixing': shangpin_leixing_list,
|
||||
'huiyuan': huiyuan_list,
|
||||
'club_id': club_id,
|
||||
'scope': scope,
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
class BkxgView(APIView):
|
||||
"""
|
||||
板块增删改统一接口
|
||||
POST /houtai/bkxg
|
||||
Body: {
|
||||
"phone": "管理员手机号",
|
||||
"action": "create | update | delete | add_items | remove_items",
|
||||
"bankuai_id": int,
|
||||
"bankuai_name": str,
|
||||
"item_type": "shangpin_leixing | huiyuan",
|
||||
"item_ids": [1,2,3]
|
||||
}
|
||||
"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def post(self, request):
|
||||
# 1. 从前端获取传递的账号
|
||||
username_from_frontend = request.data.get('phone', None)
|
||||
|
||||
# 2. 调用公共验证方法
|
||||
kefu_obj, permissions = verify_kefu_permission(request, username_from_frontend)
|
||||
|
||||
# 3. 验证失败直接返回
|
||||
if kefu_obj is None:
|
||||
return permissions
|
||||
|
||||
# 4. 检查板块管理权限
|
||||
if 'bankuai' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无板块管理权限'}, status=403)
|
||||
scope_err = block_non_group_catalog_scope(request)
|
||||
if scope_err:
|
||||
return Response({'code': 400, 'msg': scope_err})
|
||||
|
||||
# 5. 获取操作类型
|
||||
action = request.data.get('action')
|
||||
if not action:
|
||||
return Response({'code': 1, 'msg': '缺少 action 参数'}, status=400)
|
||||
|
||||
# ==================== 创建板块 ====================
|
||||
if action == 'create':
|
||||
bankuai_name = request.data.get('bankuai_name', '').strip()
|
||||
if not bankuai_name:
|
||||
return Response({'code': 1, 'msg': '板块名称不能为空'}, status=400)
|
||||
if Bankuai.query.filter(mingcheng=bankuai_name).exists():
|
||||
return Response({'code': 1, 'msg': '板块名称已存在'}, status=400)
|
||||
|
||||
shangpin_ids = request.data.get('shangpin_ids', [])
|
||||
huiyuan_ids = request.data.get('huiyuan_ids', [])
|
||||
|
||||
with transaction.atomic():
|
||||
new_bk = Bankuai.query.create(mingcheng=bankuai_name)
|
||||
if shangpin_ids:
|
||||
ShangpinLeixing.query.filter(
|
||||
id__in=shangpin_ids,
|
||||
bankuai__isnull=True
|
||||
).update(bankuai=new_bk)
|
||||
if huiyuan_ids:
|
||||
Huiyuan.query.filter(
|
||||
huiyuan_id__in=huiyuan_ids,
|
||||
bankuai__isnull=True
|
||||
).update(bankuai=new_bk)
|
||||
|
||||
return Response({
|
||||
'code': 0,
|
||||
'msg': '创建成功',
|
||||
'data': {'bankuai_id': new_bk.bankuai_id}
|
||||
})
|
||||
|
||||
# ==================== 以下操作需要 bankuai_id ====================
|
||||
bankuai_id = request.data.get('bankuai_id')
|
||||
if not bankuai_id:
|
||||
return Response({'code': 1, 'msg': '缺少 bankuai_id'}, status=400)
|
||||
|
||||
try:
|
||||
bk = Bankuai.query.get(bankuai_id=bankuai_id)
|
||||
except Bankuai.DoesNotExist:
|
||||
return Response({'code': 1, 'msg': '板块不存在'}, status=404)
|
||||
|
||||
# ==================== 修改板块名称 ====================
|
||||
if action == 'update':
|
||||
new_name = request.data.get('bankuai_name', '').strip()
|
||||
if not new_name:
|
||||
return Response({'code': 1, 'msg': '板块名称不能为空'}, status=400)
|
||||
if Bankuai.query.filter(mingcheng=new_name).exclude(bankuai_id=bankuai_id).exists():
|
||||
return Response({'code': 1, 'msg': '板块名称已存在'}, status=400)
|
||||
bk.mingcheng = new_name
|
||||
bk.save()
|
||||
return Response({'code': 0, 'msg': '修改成功'})
|
||||
|
||||
# ==================== 删除板块 ====================
|
||||
elif action == 'delete':
|
||||
with transaction.atomic():
|
||||
ShangpinLeixing.query.filter(bankuai=bk).update(bankuai=None)
|
||||
Huiyuan.query.filter(bankuai=bk).update(bankuai=None)
|
||||
bk.delete()
|
||||
return Response({'code': 0, 'msg': '删除成功'})
|
||||
|
||||
# ==================== 添加绑定 ====================
|
||||
elif action == 'add_items':
|
||||
item_type = request.data.get('item_type')
|
||||
item_ids = request.data.get('item_ids', [])
|
||||
if not item_type or not item_ids:
|
||||
return Response({'code': 1, 'msg': '缺少 item_type 或 item_ids'}, status=400)
|
||||
|
||||
if item_type == 'shangpin_leixing':
|
||||
ShangpinLeixing.query.filter(
|
||||
id__in=item_ids,
|
||||
bankuai__isnull=True
|
||||
).update(bankuai=bk)
|
||||
elif item_type == 'huiyuan':
|
||||
Huiyuan.query.filter(
|
||||
huiyuan_id__in=item_ids,
|
||||
bankuai__isnull=True
|
||||
).update(bankuai=bk)
|
||||
else:
|
||||
return Response({'code': 1, 'msg': '无效的 item_type'}, status=400)
|
||||
return Response({'code': 0, 'msg': '添加成功'})
|
||||
|
||||
# ==================== 移除绑定 ====================
|
||||
elif action == 'remove_items':
|
||||
item_type = request.data.get('item_type')
|
||||
item_ids = request.data.get('item_ids', [])
|
||||
if not item_type or not item_ids:
|
||||
return Response({'code': 1, 'msg': '缺少 item_type 或 item_ids'}, status=400)
|
||||
|
||||
if item_type == 'shangpin_leixing':
|
||||
ShangpinLeixing.query.filter(
|
||||
id__in=item_ids,
|
||||
bankuai=bk
|
||||
).update(bankuai=None)
|
||||
elif item_type == 'huiyuan':
|
||||
Huiyuan.query.filter(
|
||||
huiyuan_id__in=item_ids,
|
||||
bankuai=bk
|
||||
).update(bankuai=None)
|
||||
else:
|
||||
return Response({'code': 1, 'msg': '无效的 item_type'}, status=400)
|
||||
return Response({'code': 0, 'msg': '移除成功'})
|
||||
|
||||
else:
|
||||
return Response({'code': 1, 'msg': '未知操作'}, status=400)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user