fix: 待收款驳回按业务单号查打款记录,避免 pk 误查导致 400

This commit is contained in:
XingQue
2026-07-30 19:06:38 +08:00
parent 9df450b278
commit 6f4e458871
2 changed files with 60 additions and 33 deletions

View File

@@ -1314,6 +1314,36 @@ def mark_transfer_success(auto_record, *, wechat_transfer_no=None, with_accounti
return True return True
def _lock_auto_record_by_audit(audit):
"""
按审核单锁定关联打款记录。
audit.tixian_auto_id 存的是 TixianAutoRecord.tixian_id业务单号不是自增 pk。
"""
auto = None
auto_id = (getattr(audit, 'tixian_auto_id', None) or '').strip()
if auto_id:
auto = (
TixianAutoRecord.objects.select_for_update()
.filter(tixian_id=auto_id)
.first()
)
# 兼容极少数历史数据误存自增 id
if auto is None and auto_id.isdigit():
auto = (
TixianAutoRecord.objects.select_for_update()
.filter(pk=int(auto_id))
.first()
)
if auto is None and getattr(audit, 'shenhe_danhao', None):
auto = (
TixianAutoRecord.objects.select_for_update()
.filter(shenhe_danhao=audit.shenhe_danhao)
.order_by('-CreateTime')
.first()
)
return auto
def admin_mark_pending_collect_success(audit, tixian, kefu_uid, *, with_accounting=True): def admin_mark_pending_collect_success(audit, tixian, kefu_uid, *, with_accounting=True):
""" """
客服强制:待收款(6) → 提现成功(2)。 客服强制:待收款(6) → 提现成功(2)。
@@ -1323,25 +1353,18 @@ def admin_mark_pending_collect_success(audit, tixian, kefu_uid, *, with_accounti
audit = TixianShenheJilu.objects.select_for_update().get(pk=audit.pk) audit = TixianShenheJilu.objects.select_for_update().get(pk=audit.pk)
tixian = Tixianjilu.objects.select_for_update().get(pk=tixian.pk) tixian = Tixianjilu.objects.select_for_update().get(pk=tixian.pk)
if int(audit.zhuangtai) != 6 or int(tixian.zhuangtai) != 6: if int(audit.zhuangtai) != 6 or int(tixian.zhuangtai) != 6:
raise ValueError('仅待收款状态可标记为已收款') raise ValueError(
f'仅待收款状态可标记为已收款'
f'(当前提现单={tixian.zhuangtai},审核单={audit.zhuangtai})'
)
# 1) 先改状态 # 1) 先改状态
sync_audit_and_jilu_status(audit, 2, shenhe_ren_id=kefu_uid or '') sync_audit_and_jilu_status(audit, 2, shenhe_ren_id=(kefu_uid or '')[:11])
tixian.shenheid = kefu_uid or tixian.shenheid or '' tixian.shenheid = (kefu_uid or tixian.shenheid or '')[:11]
tixian.save(update_fields=['shenheid', 'UpdateTime']) tixian.save(update_fields=['shenheid', 'UpdateTime'])
# 2) 关联打款单:处理中→成功;无打款单则直接按审核金额记账 # 2) 关联打款单:处理中→成功;无打款单则直接按审核金额记账
auto = None auto = _lock_auto_record_by_audit(audit)
auto_id = (getattr(audit, 'tixian_auto_id', None) or '').strip()
if auto_id:
auto = TixianAutoRecord.objects.select_for_update().filter(pk=auto_id).first()
if auto is None and audit.shenhe_danhao:
auto = (
TixianAutoRecord.objects.select_for_update()
.filter(shenhe_danhao=audit.shenhe_danhao)
.order_by('-CreateTime')
.first()
)
if auto is not None: if auto is not None:
if int(auto.zhuangtai) == 0: if int(auto.zhuangtai) == 0:
@@ -1392,26 +1415,26 @@ def admin_reject_pending_or_auditing(
""" """
audit = TixianShenheJilu.objects.select_for_update().get(pk=audit.pk) audit = TixianShenheJilu.objects.select_for_update().get(pk=audit.pk)
tixian = Tixianjilu.objects.select_for_update().get(pk=tixian.pk) tixian = Tixianjilu.objects.select_for_update().get(pk=tixian.pk)
cur = int(audit.zhuangtai) jt = int(tixian.zhuangtai)
if cur not in (1, 6): at = int(audit.zhuangtai)
raise ValueError('仅审核中/待收款可驳回') if jt not in (1, 6) or at not in (1, 6):
if int(tixian.zhuangtai) != cur: raise ValueError(
raise ValueError('提现单与审核单状态不一致') f'仅审核中/待收款可驳回(当前提现单={jt},审核单={at})'
)
# 两边都可驳回但不同步时,以审核单为准对齐提现单后再驳回
if jt != at:
logger.warning(
'驳回前状态不一致,对齐提现单→审核单 tixian=%s jt=%s at=%s',
tixian.id, jt, at,
)
tixian.zhuangtai = at
tixian.save(update_fields=['zhuangtai', 'UpdateTime'])
reason = (reason or '').strip()[:500] or '客服驳回' reason = (reason or '').strip()[:500] or '客服驳回'
kefu_uid = (kefu_uid or '')[:11]
# 待收款可能已有打款单:先失败释放限额,避免用户还能收款 # 待收款可能已有打款单:先失败释放限额,避免用户还能收款
auto_id = (getattr(audit, 'tixian_auto_id', None) or '').strip() auto = _lock_auto_record_by_audit(audit)
auto = None
if auto_id:
auto = TixianAutoRecord.objects.select_for_update().filter(pk=auto_id).first()
if auto is None and audit.shenhe_danhao:
auto = (
TixianAutoRecord.objects.select_for_update()
.filter(shenhe_danhao=audit.shenhe_danhao, zhuangtai=0)
.order_by('-CreateTime')
.first()
)
if auto is not None and int(auto.zhuangtai) == 0: if auto is not None and int(auto.zhuangtai) == 0:
_close_auto_record_failed(auto, reason) _close_auto_record_failed(auto, reason)
@@ -1419,7 +1442,7 @@ def admin_reject_pending_or_auditing(
sync_audit_and_jilu_status( sync_audit_and_jilu_status(
audit, 5, audit, 5,
bhliyou=reason, bhliyou=reason,
bo_hui_ren_id=kefu_uid or '', bo_hui_ren_id=kefu_uid or None,
tixian_auto_id=None, tixian_auto_id=None,
) )
tixian.shenheid = kefu_uid or tixian.shenheid or '' tixian.shenheid = kefu_uid or tixian.shenheid or ''
@@ -1437,7 +1460,7 @@ def admin_reject_pending_or_auditing(
shouxufei=audit.shouxufei, shouxufei=audit.shouxufei,
refund_fee=bool(refund_fee), refund_fee=bool(refund_fee),
apply_entry_freeze=bool(apply_entry_freeze), apply_entry_freeze=bool(apply_entry_freeze),
biz_id=f'withdraw_reject:admin:{tixian.id}:{cur}', biz_id=f'withdraw_reject:admin:{tixian.id}:{at}',
freeze_reason=f'提现驳回退款 #{tixian.id}', freeze_reason=f'提现驳回退款 #{tixian.id}',
) )
return refund_result return refund_result

View File

@@ -728,7 +728,10 @@ class KefuWithdrawActionView(APIView):
# action=2审核中/待收款 → 驳回 # action=2审核中/待收款 → 驳回
if action == 2: if action == 2:
if cur not in (1, 6) or int(audit.zhuangtai) not in (1, 6): if cur not in (1, 6) or int(audit.zhuangtai) not in (1, 6):
raise ValueError(f'提现记录{tixian_id}:仅审核中/待收款可驳回') raise ValueError(
f'提现记录{tixian_id}:仅审核中/待收款可驳回'
f'(当前提现单={cur},审核单={audit.zhuangtai})'
)
admin_reject_pending_or_auditing( admin_reject_pending_or_auditing(
audit, tixian, user, kefu_uid, reason, audit, tixian, user, kefu_uid, reason,
refund_principal=refund_principal, refund_principal=refund_principal,
@@ -902,6 +905,7 @@ class KefuWithdrawActionView(APIView):
) )
except ValueError as e: except ValueError as e:
logger.warning('kefu_txsh_action 业务拒绝: %s data=%s', e, request.data)
return Response({'code': 400, 'msg': str(e)}, status=status.HTTP_400_BAD_REQUEST) return Response({'code': 400, 'msg': str(e)}, status=status.HTTP_400_BAD_REQUEST)
except Exception as e: except Exception as e:
logger.error(f'处理提现事务失败: {e}', exc_info=True) logger.error(f'处理提现事务失败: {e}', exc_info=True)