商家罚款增加平台审核:新增状态5、证据图、审核API;审核通过前不影响抢单,提现仍拦截未结案罚单
This commit is contained in:
@@ -12,7 +12,7 @@ from .view import (GetRolePermissionView,
|
||||
ShopModifyView, ShopPublicTypeAndAuditView, ShopListForProductView, ShopProductModifyView,
|
||||
ShopProductTypeMappingView, ProductListView, ProductModifyView, KefuChatPermissionsView,
|
||||
FineApplyView, PunishDashouView,
|
||||
FaKuanTongJiView, FaKuanLieBiaoView, FaKuanChuLiView, FaKuanChuangJianView,
|
||||
FaKuanTongJiView, FaKuanLieBiaoView, FaKuanChuLiView, FaKuanChuangJianView, FaKuanPingTaiShenHeView,
|
||||
HqbkxxView,BkxgView,CaiwuView,CwhybkhqView, HybkjtsjView, SzxxView, CwddhqlxView, CwhqjtddsjView,
|
||||
CwqtczhqView, KhpzhqView, ChzsgcView,KhgglView, ShgxgsjView, KhjlglView, KhjlczView, ZxkfghdsView)
|
||||
from config.views import MiniappScriptHoutaiListView, MiniappScriptHoutaiModifyView
|
||||
@@ -89,6 +89,7 @@ urlpatterns = [
|
||||
path('htglyhqcfsltj', FaKuanTongJiView.as_view(),name='后台罚单统计图片'), # 罚款统计
|
||||
path('hthqfklb', FaKuanLieBiaoView.as_view(),name='后台罚单列表'), # 罚款列表
|
||||
path('glyclfk', FaKuanChuLiView.as_view(),name='后台罚单操作'), # 处理罚款
|
||||
path('glyptshfk', FaKuanPingTaiShenHeView.as_view(), name='后台罚款平台审核'),
|
||||
path('htfksc', FaKuanChuangJianView.as_view(),name='后台生成罚单'), # 创建罚款
|
||||
path('kffkdssq', FineApplyView.as_view(), name='客服罚款申请'), # 客服罚款申请
|
||||
path('kpcf', PunishDashouView.as_view(), name='客服处罚打手'), # 客服处罚打手
|
||||
|
||||
@@ -6609,6 +6609,72 @@ class FaKuanChuLiView(APIView):
|
||||
return Response({'code': 500, 'msg': '系统繁忙'})
|
||||
|
||||
|
||||
class FaKuanPingTaiShenHeView(APIView):
|
||||
"""
|
||||
平台审核商家提交的罚款(同意/驳回)
|
||||
POST /houtai/glyptshfk
|
||||
action: platform_approve | platform_reject
|
||||
"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
parser_classes = [MultiPartParser, FormParser, JSONParser]
|
||||
|
||||
def post(self, request):
|
||||
try:
|
||||
from utils.penalty_status import (
|
||||
PENALTY_PLATFORM_AUDIT, PENALTY_PENDING_PAY, PENALTY_APPEALING, PENALTY_REJECTED,
|
||||
)
|
||||
username = request.data.get('username', '').strip()
|
||||
penalty_id = request.data.get('penalty_id') or request.data.get('fadan_id')
|
||||
action = request.data.get('action', '').strip()
|
||||
chuli_liyou = request.data.get('chuli_liyou', '').strip()
|
||||
|
||||
if not all([username, penalty_id, action]):
|
||||
return Response({'code': 400, 'msg': '参数不完整'})
|
||||
|
||||
kefu, permissions = verify_kefu_permission(request, username)
|
||||
if kefu is None:
|
||||
return permissions
|
||||
|
||||
with transaction.atomic():
|
||||
try:
|
||||
penalty = Penalty.objects.select_for_update().get(id=penalty_id)
|
||||
except Penalty.DoesNotExist:
|
||||
return Response({'code': 404, 'msg': '罚单不存在'})
|
||||
|
||||
deny = forbid_penalty_out_of_scope(request, penalty)
|
||||
if deny:
|
||||
return deny
|
||||
|
||||
if penalty.Status != PENALTY_PLATFORM_AUDIT:
|
||||
return Response({'code': 400, 'msg': '当前状态不可平台审核'})
|
||||
|
||||
if not check_fadan_permission(permissions, penalty.Identity):
|
||||
return Response({'code': 403, 'msg': '无权限处理该类罚单'})
|
||||
|
||||
if action == 'platform_approve':
|
||||
if penalty.AppealReason:
|
||||
penalty.Status = PENALTY_APPEALING
|
||||
else:
|
||||
penalty.Status = PENALTY_PENDING_PAY
|
||||
penalty.ApproveReason = chuli_liyou or penalty.ApproveReason or ''
|
||||
elif action == 'platform_reject':
|
||||
penalty.Status = PENALTY_REJECTED
|
||||
penalty.RejectReason = chuli_liyou or '平台审核驳回'
|
||||
else:
|
||||
return Response({'code': 400, 'msg': '无效的操作类型'})
|
||||
|
||||
penalty.ProcessorID = request.user.Phone
|
||||
penalty.ProcessorIdentity = 3
|
||||
penalty.save()
|
||||
|
||||
logger.info(f"罚款平台审核成功: {penalty_id}, 操作: {action}")
|
||||
return Response({'code': 0, 'msg': '平台审核完成'})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"罚款平台审核异常: {traceback.format_exc()}")
|
||||
return Response({'code': 500, 'msg': '系统繁忙'})
|
||||
|
||||
|
||||
class FaKuanChuangJianView(APIView):
|
||||
"""
|
||||
管理员创建罚款
|
||||
|
||||
@@ -6,6 +6,7 @@ from backend.view import (
|
||||
ClubMemberDisableView,
|
||||
ClubMemberEnableView,
|
||||
FaKuanChuLiView,
|
||||
FaKuanPingTaiShenHeView,
|
||||
FaKuanChuangJianView,
|
||||
FaKuanLieBiaoView,
|
||||
FaKuanTongJiView,
|
||||
@@ -125,6 +126,7 @@ urlpatterns = [
|
||||
path('houtai/htglyhqcfsltj', FaKuanTongJiView.as_view(), name='jituan_penalty_stats'),
|
||||
path('houtai/hthqfklb', FaKuanLieBiaoView.as_view(), name='jituan_penalty_list'),
|
||||
path('houtai/glyclfk', FaKuanChuLiView.as_view(), name='jituan_penalty_action'),
|
||||
path('houtai/glyptshfk', FaKuanPingTaiShenHeView.as_view(), name='jituan_penalty_platform_audit'),
|
||||
path('houtai/htfksc', FaKuanChuangJianView.as_view(), name='jituan_penalty_create'),
|
||||
path('houtai/kefu-cfgl', KefuPunishmentListView.as_view(), name='jituan_kefu_cfgl'),
|
||||
path('houtai/khggl', KhgglView.as_view(), name='jituan_khggl'),
|
||||
|
||||
@@ -444,7 +444,7 @@ class OrderPlayerHistory(QModel):
|
||||
class Penalty(QModel):
|
||||
"""罚单表——平台各类处罚信息
|
||||
|
||||
状态码:1=待缴纳, 2=已缴纳, 3=申诉中, 4=已驳回
|
||||
状态码:1=待缴纳, 2=已缴纳, 3=申诉中, 4=已驳回, 5=平台审核中
|
||||
被处罚者身份(shenfen):1=打手, 2=管事, 3=商家, 4=组长
|
||||
"""
|
||||
|
||||
@@ -475,7 +475,7 @@ class Penalty(QModel):
|
||||
db_column='guanliandingdan_id', verbose_name='关联订单ID',
|
||||
)
|
||||
Status = models.IntegerField(
|
||||
choices=[(1, '待缴纳'), (2, '已缴纳'), (3, '申诉中'), (4, '已驳回')],
|
||||
choices=[(1, '待缴纳'), (2, '已缴纳'), (3, '申诉中'), (4, '已驳回'), (5, '平台审核中')],
|
||||
default=1, db_index=True,
|
||||
db_column='zhuangtai', verbose_name='罚单状态',
|
||||
)
|
||||
|
||||
@@ -2294,6 +2294,20 @@ class ShangjiaDingdanXiangqingView(APIView):
|
||||
if fadan_obj:
|
||||
ct = fmt_datetime(fadan_obj.CreateTime)
|
||||
ut = fmt_datetime(fadan_obj.UpdateTime)
|
||||
zhengju_urls = list(
|
||||
PenaltyAppealImage.query.filter(Penalty=fadan_obj, Purpose=1).values_list('ImageURL', flat=True)
|
||||
)
|
||||
shensu_urls = list(
|
||||
PenaltyAppealImage.query.filter(Penalty=fadan_obj, Purpose=2).values_list('ImageURL', flat=True)
|
||||
)
|
||||
zhengju_imgs = [
|
||||
{'id': t.id, 'url': t.ImageURL}
|
||||
for t in PenaltyAppealImage.query.filter(Penalty=fadan_obj, Purpose=1)
|
||||
]
|
||||
shensu_imgs = [
|
||||
{'id': t.id, 'url': t.ImageURL}
|
||||
for t in PenaltyAppealImage.query.filter(Penalty=fadan_obj, Purpose=2)
|
||||
]
|
||||
fadan_dict = {
|
||||
'id': fadan_obj.id,
|
||||
'chufaliyou': fadan_obj.Reason or '',
|
||||
@@ -2306,6 +2320,8 @@ class ShangjiaDingdanXiangqingView(APIView):
|
||||
'yingde_fenhong': float(fadan_obj.ApplicantBonusAmount or 0),
|
||||
'fenhong_lilv': float(fadan_obj.ApplicantBonusRate or 0),
|
||||
'fenhong_yiruzhang': bool(fadan_obj.BonusCredited),
|
||||
'zhengju_tupian': zhengju_imgs,
|
||||
'shensu_tupian': shensu_imgs,
|
||||
'CreateTime': ct,
|
||||
'create_time': ct,
|
||||
'UpdateTime': ut,
|
||||
@@ -4147,6 +4163,20 @@ class DashouCOSZhengshuView(APIView):
|
||||
).first()
|
||||
if not fadan:
|
||||
return Response({'code': 403, 'msg': '罚单不存在或无权操作'}, status=403)
|
||||
elif yongtu == 'fakuan_evidence_draft':
|
||||
# 商家申请罚款前上传证据图(仅需订单归属校验)
|
||||
if not dingdan_id:
|
||||
return Response({'code': 400, 'msg': '缺少订单ID'}, status=400)
|
||||
try:
|
||||
shangjia_profile = request.user.ShopProfile
|
||||
if shangjia_profile.zhuangtai != 1:
|
||||
return Response({'code': 403, 'msg': '商家状态异常'}, status=403)
|
||||
except Exception:
|
||||
return Response({'code': 403, 'msg': '非商家无权上传'}, status=403)
|
||||
try:
|
||||
MerchantOrderExt.query.get(Order__OrderID=dingdan_id, MerchantID=request.user.UserUID)
|
||||
except MerchantOrderExt.DoesNotExist:
|
||||
return Response({'code': 403, 'msg': '订单不存在或无权操作'}, status=403)
|
||||
else:
|
||||
# 默认为订单相关,需要验证订单且打手必须接单
|
||||
try:
|
||||
@@ -4190,6 +4220,10 @@ class DashouCOSZhengshuView(APIView):
|
||||
resources.append(
|
||||
f"qcs::cos:{settings.COS_REGION}:uid/{settings.COS_APPID}:{settings.COS_BUCKET}/fakuan/shangjiafakuan/zhengju/*"
|
||||
)
|
||||
elif yongtu == 'fakuan_evidence_draft':
|
||||
resources.append(
|
||||
f"qcs::cos:{settings.COS_REGION}:uid/{settings.COS_APPID}:{settings.COS_BUCKET}/fakuan/shangjiafakuan/zhengju/*"
|
||||
)
|
||||
else:
|
||||
resources.append(
|
||||
f"qcs::cos:{settings.COS_REGION}:uid/{settings.COS_APPID}:{settings.COS_BUCKET}/order/{dingdan_id}/*"
|
||||
@@ -6801,10 +6835,19 @@ class ShangjiaFakuanApplyView(APIView):
|
||||
chufa_liyou = request.data.get('chufa_liyou', '').strip()
|
||||
fakuanjine = request.data.get('fakuanjine', 0)
|
||||
yingxiang_qiangdan = int(request.data.get('yingxiang_qiangdan', 1))
|
||||
evidence_urls = request.data.get('evidence_urls') or []
|
||||
|
||||
if not dingdan_id or not chufa_liyou or not fakuanjine:
|
||||
return Response({'code': 2, 'msg': '参数不完整'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
if not isinstance(evidence_urls, list):
|
||||
return Response({'code': 2, 'msg': '证据图片格式错误'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
evidence_urls = [str(u).strip() for u in evidence_urls if str(u).strip()]
|
||||
if len(evidence_urls) > 9:
|
||||
return Response({'code': 2, 'msg': '证据图片最多9张'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
if len(evidence_urls) < 1:
|
||||
return Response({'code': 2, 'msg': '请至少上传1张证据图片'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
try:
|
||||
fakuanjine = float(fakuanjine)
|
||||
if fakuanjine <= 0:
|
||||
@@ -6838,6 +6881,8 @@ class ShangjiaFakuanApplyView(APIView):
|
||||
if staff_member is not None:
|
||||
staff_kefu_id = getattr(staff_member, 'staff_user_id', None) or None
|
||||
|
||||
from utils.penalty_status import PENALTY_PLATFORM_AUDIT
|
||||
|
||||
with transaction.atomic():
|
||||
fadan = Penalty.query.create(
|
||||
PenalizedUserID=dashou_id,
|
||||
@@ -6846,7 +6891,7 @@ class ShangjiaFakuanApplyView(APIView):
|
||||
Reason=chufa_liyou,
|
||||
FineAmount=fakuanjine,
|
||||
RelatedOrderID=dingdan_id,
|
||||
Status=1, # 待缴纳
|
||||
Status=PENALTY_PLATFORM_AUDIT, # 平台审核中,通过后变为待缴纳
|
||||
AffectsGrabbing=yingxiang_qiangdan,
|
||||
ApplicantIdentity=5, # 申请人是商家
|
||||
ClubID=resolve_penalty_club_id(
|
||||
@@ -6858,9 +6903,16 @@ class ShangjiaFakuanApplyView(APIView):
|
||||
),
|
||||
ShopStaffUserID=staff_kefu_id,
|
||||
)
|
||||
for url in evidence_urls:
|
||||
PenaltyAppealImage.query.create(
|
||||
Penalty=fadan,
|
||||
PenalizedUserID=dashou_id,
|
||||
ImageURL=url,
|
||||
Purpose=1,
|
||||
)
|
||||
lock_penalty_bonus(fadan)
|
||||
logger.info(f"商家{shangjia_id}对订单{dingdan_id}打手{dashou_id}罚款成功,金额{fakuanjine}")
|
||||
return Response({'code': 0, 'msg': '罚款申请已提交'})
|
||||
logger.info(f"商家{shangjia_id}对订单{dingdan_id}打手{dashou_id}提交罚款申请(平台审核),金额{fakuanjine}")
|
||||
return Response({'code': 0, 'msg': '罚款申请已提交,等待平台审核', 'data': {'fadan_id': fadan.id}})
|
||||
|
||||
|
||||
class ShangjiaFakuaiXiugaiView(APIView):
|
||||
@@ -6944,8 +6996,9 @@ class ShangjiaFakuaiXiugaiView(APIView):
|
||||
return Response({'code': 0, 'msg': '退款理由修改成功'})
|
||||
|
||||
def _modify_penalty(self, fadan, liyou, jine_str, processor_id=None):
|
||||
"""修改罚款(仅状态1待缴纳 或 3申诉中)"""
|
||||
if fadan.Status not in (1, 3):
|
||||
"""修改罚款(待缴纳 / 申诉中 / 平台审核中)"""
|
||||
from utils.penalty_status import PENALTY_PENDING_PAY, PENALTY_APPEALING, PENALTY_PLATFORM_AUDIT
|
||||
if fadan.Status not in (PENALTY_PENDING_PAY, PENALTY_APPEALING, PENALTY_PLATFORM_AUDIT):
|
||||
return Response({'code': 400, 'msg': '当前罚单状态不可修改'})
|
||||
if not liyou.strip():
|
||||
return Response({'code': 400, 'msg': '罚款理由不能为空'})
|
||||
@@ -6966,13 +7019,14 @@ class ShangjiaFakuaiXiugaiView(APIView):
|
||||
return Response({'code': 0, 'msg': '罚款修改成功'})
|
||||
|
||||
def _cancel_penalty(self, fadan, liyou, processor_id=None):
|
||||
"""撤销罚款(状态1或3 → 状态4 已驳回)"""
|
||||
if fadan.Status not in (1, 3):
|
||||
"""撤销罚款(待缴纳 / 申诉中 / 平台审核中 → 已驳回)"""
|
||||
from utils.penalty_status import PENALTY_PENDING_PAY, PENALTY_APPEALING, PENALTY_PLATFORM_AUDIT, PENALTY_REJECTED
|
||||
if fadan.Status not in (PENALTY_PENDING_PAY, PENALTY_APPEALING, PENALTY_PLATFORM_AUDIT):
|
||||
return Response({'code': 400, 'msg': '当前罚单状态不可撤销'})
|
||||
if not liyou.strip():
|
||||
return Response({'code': 400, 'msg': '驳回理由不能为空'})
|
||||
with transaction.atomic():
|
||||
fadan.Status = 4 # 已驳回
|
||||
fadan.Status = PENALTY_REJECTED # 已驳回
|
||||
fadan.RejectReason = liyou[:500]
|
||||
if processor_id:
|
||||
fadan.ProcessorID = processor_id
|
||||
@@ -6981,8 +7035,9 @@ class ShangjiaFakuaiXiugaiView(APIView):
|
||||
return Response({'code': 0, 'msg': '罚款已撤销(驳回)'})
|
||||
|
||||
def _resubmit_penalty(self, fadan, liyou, jine_str, processor_id=None):
|
||||
"""再次申请罚款(状态4 → 状态1,修改理由和金额)"""
|
||||
if fadan.Status != 4:
|
||||
"""再次申请罚款(已驳回 → 平台审核中)"""
|
||||
from utils.penalty_status import PENALTY_REJECTED, PENALTY_PLATFORM_AUDIT
|
||||
if fadan.Status != PENALTY_REJECTED:
|
||||
return Response({'code': 400, 'msg': '只有已驳回的罚单可再次申请'})
|
||||
if not liyou.strip():
|
||||
return Response({'code': 400, 'msg': '罚款理由不能为空'})
|
||||
@@ -6993,7 +7048,7 @@ class ShangjiaFakuaiXiugaiView(APIView):
|
||||
except:
|
||||
return Response({'code': 400, 'msg': '罚款金额必须为正数'})
|
||||
with transaction.atomic():
|
||||
fadan.Status = 1 # 待缴纳
|
||||
fadan.Status = PENALTY_PLATFORM_AUDIT
|
||||
fadan.Reason = liyou[:500]
|
||||
fadan.FineAmount = jine
|
||||
fadan.RejectReason = '' # 清空驳回理由
|
||||
@@ -7007,7 +7062,8 @@ class ShangjiaFakuaiXiugaiView(APIView):
|
||||
|
||||
def _manage_penalty_evidence(self, fadan, data):
|
||||
"""管理罚单证据图片(Purpose=1),与申诉图片严格隔离"""
|
||||
if fadan.Status not in (1, 3):
|
||||
from utils.penalty_status import PENALTY_PENDING_PAY, PENALTY_APPEALING, PENALTY_PLATFORM_AUDIT
|
||||
if fadan.Status not in (PENALTY_PENDING_PAY, PENALTY_APPEALING, PENALTY_PLATFORM_AUDIT):
|
||||
return Response({'code': 400, 'msg': '当前罚单状态不可修改证据图片'})
|
||||
add_urls = data.get('add_urls') or []
|
||||
remove_ids = data.get('remove_ids') or []
|
||||
@@ -7018,6 +7074,9 @@ class ShangjiaFakuaiXiugaiView(APIView):
|
||||
PenaltyAppealImage.query.filter(
|
||||
Penalty=fadan, Purpose=1, id__in=remove_ids
|
||||
).delete()
|
||||
existing_count = PenaltyAppealImage.query.filter(Penalty=fadan, Purpose=1).count()
|
||||
if existing_count + len(add_urls) > 9:
|
||||
return Response({'code': 400, 'msg': '证据图片最多9张'})
|
||||
for url in add_urls:
|
||||
url = str(url).strip()
|
||||
if not url:
|
||||
|
||||
@@ -11601,6 +11601,7 @@ class FaKuanJiFenTongJiView(APIView):
|
||||
total=Count('id'),
|
||||
daijiaona=Count('id', filter=Q(Status=1)),
|
||||
shensuzhong=Count('id', filter=Q(Status=3)),
|
||||
pingtai_shenhe=Count('id', filter=Q(Status=5)),
|
||||
yijiaona=Count('id', filter=Q(Status=2)),
|
||||
yibohui=Count('id', filter=Q(Status=4)),
|
||||
)
|
||||
@@ -11622,6 +11623,7 @@ class FaKuanJiFenTongJiView(APIView):
|
||||
"total": fadan_stats['total'],
|
||||
"daijiaona": fadan_stats['daijiaona'],
|
||||
"shensuzhong": fadan_stats['shensuzhong'],
|
||||
"pingtai_shenhe": fadan_stats['pingtai_shenhe'],
|
||||
"yijiaona": fadan_stats['yijiaona'],
|
||||
"yibohui": fadan_stats['yibohui'],
|
||||
},
|
||||
@@ -11686,7 +11688,7 @@ class DaShouFaKuanLieBiaoView(APIView):
|
||||
qs = Penalty.query.filter(PenalizedUserID=yonghuid)
|
||||
|
||||
# 状态筛选
|
||||
if zhuangtai is not None and int(zhuangtai) in [1, 2, 3, 4]:
|
||||
if zhuangtai is not None and int(zhuangtai) in [1, 2, 3, 4, 5]:
|
||||
qs = qs.filter(Status=int(zhuangtai))
|
||||
|
||||
# 订单号模糊搜索
|
||||
@@ -11805,6 +11807,8 @@ class ShangjiaCufaTongjiView(APIView):
|
||||
yijiaona_jine=Sum('FineAmount', filter=Q(Status=2)),
|
||||
shensuzhong=Count('id', filter=Q(Status=3)),
|
||||
shensuzhong_jine=Sum('FineAmount', filter=Q(Status=3)),
|
||||
pingtai_shenhe=Count('id', filter=Q(Status=5)),
|
||||
pingtai_shenhe_jine=Sum('FineAmount', filter=Q(Status=5)),
|
||||
yibohui=Count('id', filter=Q(Status=4)),
|
||||
yibohui_jine=Sum('FineAmount', filter=Q(Status=4)),
|
||||
shijidaozhang_jine=Sum(
|
||||
@@ -11842,6 +11846,8 @@ class ShangjiaCufaTongjiView(APIView):
|
||||
'yijiaona_jine': _money_str(fadan_agg['yijiaona_jine']),
|
||||
'shensuzhong': fadan_agg['shensuzhong'] or 0,
|
||||
'shensuzhong_jine': _money_str(fadan_agg['shensuzhong_jine']),
|
||||
'pingtai_shenhe': fadan_agg['pingtai_shenhe'] or 0,
|
||||
'pingtai_shenhe_jine': _money_str(fadan_agg['pingtai_shenhe_jine']),
|
||||
'yibohui': fadan_agg['yibohui'] or 0,
|
||||
'yibohui_jine': _money_str(fadan_agg['yibohui_jine']),
|
||||
'shijidaozhang_jine': _money_str(fadan_agg['shijidaozhang_jine']),
|
||||
@@ -11889,7 +11895,7 @@ class ShangjiaFakuanLieBiaoView(APIView):
|
||||
sousuo_dingdan_id = str(request.data.get('sousuo_dingdan_id', '')).strip()
|
||||
|
||||
qs = Penalty.query.filter(ApplicantID=yonghuid)
|
||||
if zhuangtai is not None and int(zhuangtai) in [1, 2, 3, 4]:
|
||||
if zhuangtai is not None and int(zhuangtai) in [1, 2, 3, 4, 5]:
|
||||
qs = qs.filter(Status=int(zhuangtai))
|
||||
if sousuo_dingdan_id:
|
||||
qs = qs.filter(RelatedOrderID__icontains=sousuo_dingdan_id)
|
||||
@@ -12002,14 +12008,23 @@ class FaKuanShenSuView(APIView):
|
||||
except Penalty.DoesNotExist:
|
||||
return Response({'code': 404, 'msg': '罚单不存在或无权操作'}, status=404)
|
||||
|
||||
# 只允许待缴纳状态(状态1)且没有驳回理由的罚单申诉
|
||||
if fadan.Status != 1:
|
||||
# 待缴纳(1)或平台审核中(5)可申诉;平台审核中仅保存申诉内容,不改变状态
|
||||
from utils.penalty_status import (
|
||||
PENALTY_PENDING_PAY, PENALTY_APPEALING, PENALTY_PLATFORM_AUDIT,
|
||||
)
|
||||
if fadan.Status not in (PENALTY_PENDING_PAY, PENALTY_PLATFORM_AUDIT):
|
||||
return Response({'code': 400, 'msg': '罚单状态不允许申诉'}, status=400)
|
||||
if fadan.RejectReason:
|
||||
if fadan.Status == PENALTY_PENDING_PAY and fadan.RejectReason:
|
||||
return Response({'code': 400, 'msg': '该罚单申诉已被驳回,不可再次申诉'}, status=400)
|
||||
|
||||
# 更新罚单状态为申诉中,并记录理由
|
||||
fadan.Status = 3
|
||||
if not isinstance(tupian_urls, list):
|
||||
return Response({'code': 400, 'msg': '申诉图片格式错误'}, status=400)
|
||||
tupian_urls = [str(u).strip() for u in tupian_urls if str(u).strip()]
|
||||
if len(tupian_urls) > 9:
|
||||
return Response({'code': 400, 'msg': '申诉图片最多9张'}, status=400)
|
||||
|
||||
if fadan.Status == PENALTY_PENDING_PAY:
|
||||
fadan.Status = PENALTY_APPEALING
|
||||
fadan.AppealReason = shensu_liyou
|
||||
fadan.save()
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# utils/fadan_utils.py
|
||||
from orders.models import Penalty
|
||||
from utils.penalty_status import (
|
||||
PENALTY_GRAB_BLOCK_STATUSES,
|
||||
PENALTY_WITHDRAW_BLOCK_STATUSES,
|
||||
)
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger('xiaochengxu')
|
||||
@@ -19,11 +23,11 @@ def check_fadan_qiangdan_eligible(yonghuid: str, action_type: int) -> tuple:
|
||||
"""
|
||||
try:
|
||||
if action_type == 1:
|
||||
# 抢单:仅当存在“影响抢单”且“未解决”的罚单时拦截(待缴纳或申诉中)
|
||||
# 抢单:仅「影响抢单」且「平台审核通过后仍未结案」的罚单拦截
|
||||
blocked = Penalty.objects.filter(
|
||||
PenalizedUserID=yonghuid,
|
||||
AffectsGrabbing=1,
|
||||
Status__in=[1, 3] # 1=待缴纳, 3=申诉中
|
||||
Status__in=PENALTY_GRAB_BLOCK_STATUSES,
|
||||
).exists()
|
||||
if blocked:
|
||||
logger.info(f"用户 {yonghuid} 抢单被拦截:存在未解决的影响抢单罚单")
|
||||
@@ -31,10 +35,10 @@ def check_fadan_qiangdan_eligible(yonghuid: str, action_type: int) -> tuple:
|
||||
return (True, "无罚单限制")
|
||||
|
||||
elif action_type == 2:
|
||||
# 提现:只要存在任意未解决的罚单(待缴纳/申诉中),不论是否影响抢单,一律禁止提现
|
||||
# 提现:平台审核中 / 待缴纳 / 申诉中 均禁止提现
|
||||
blocked = Penalty.objects.filter(
|
||||
PenalizedUserID=yonghuid,
|
||||
Status__in=[1, 3] # 1=待缴纳, 3=申诉中
|
||||
Status__in=PENALTY_WITHDRAW_BLOCK_STATUSES,
|
||||
).exists()
|
||||
if blocked:
|
||||
logger.info(f"用户 {yonghuid} 提现被拦截:存在未解决的罚单")
|
||||
|
||||
21
utils/penalty_status.py
Normal file
21
utils/penalty_status.py
Normal file
@@ -0,0 +1,21 @@
|
||||
"""金额罚单 fadan 状态常量(与 orders.models.Penalty.Status 一致)"""
|
||||
|
||||
PENALTY_PENDING_PAY = 1 # 待缴纳(平台审核通过后)
|
||||
PENALTY_PAID = 2 # 已缴纳
|
||||
PENALTY_APPEALING = 3 # 申诉中
|
||||
PENALTY_REJECTED = 4 # 已驳回 / 打手申诉成功
|
||||
PENALTY_PLATFORM_AUDIT = 5 # 平台审核中(商家提交后,审核通过前)
|
||||
|
||||
# 影响抢单:仅平台审核通过后的未结案罚单
|
||||
PENALTY_GRAB_BLOCK_STATUSES = (PENALTY_PENDING_PAY, PENALTY_APPEALING)
|
||||
|
||||
# 影响提现:含平台审核中
|
||||
PENALTY_WITHDRAW_BLOCK_STATUSES = (PENALTY_PENDING_PAY, PENALTY_APPEALING, PENALTY_PLATFORM_AUDIT)
|
||||
|
||||
PENALTY_STATUS_LABELS = {
|
||||
1: '待缴纳',
|
||||
2: '已缴纳',
|
||||
3: '申诉中',
|
||||
4: '已驳回',
|
||||
5: '平台审核中',
|
||||
}
|
||||
Reference in New Issue
Block a user