diff --git a/users/tixian_shenhe_services.py b/users/tixian_shenhe_services.py index fae9e0d..47723db 100644 --- a/users/tixian_shenhe_services.py +++ b/users/tixian_shenhe_services.py @@ -1314,6 +1314,36 @@ def mark_transfer_success(auto_record, *, wechat_transfer_no=None, with_accounti 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): """ 客服强制:待收款(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) tixian = Tixianjilu.objects.select_for_update().get(pk=tixian.pk) if int(audit.zhuangtai) != 6 or int(tixian.zhuangtai) != 6: - raise ValueError('仅待收款状态可标记为已收款') + raise ValueError( + f'仅待收款状态可标记为已收款' + f'(当前提现单={tixian.zhuangtai},审核单={audit.zhuangtai})' + ) # 1) 先改状态 - sync_audit_and_jilu_status(audit, 2, shenhe_ren_id=kefu_uid or '') - tixian.shenheid = kefu_uid or tixian.shenheid or '' + sync_audit_and_jilu_status(audit, 2, shenhe_ren_id=(kefu_uid or '')[:11]) + tixian.shenheid = (kefu_uid or tixian.shenheid or '')[:11] tixian.save(update_fields=['shenheid', 'UpdateTime']) # 2) 关联打款单:处理中→成功;无打款单则直接按审核金额记账 - auto = None - 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() - ) + auto = _lock_auto_record_by_audit(audit) if auto is not None: 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) tixian = Tixianjilu.objects.select_for_update().get(pk=tixian.pk) - cur = int(audit.zhuangtai) - if cur not in (1, 6): - raise ValueError('仅审核中/待收款可驳回') - if int(tixian.zhuangtai) != cur: - raise ValueError('提现单与审核单状态不一致') + jt = int(tixian.zhuangtai) + at = int(audit.zhuangtai) + if jt not in (1, 6) or at not in (1, 6): + 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 '客服驳回' + kefu_uid = (kefu_uid or '')[:11] # 待收款可能已有打款单:先失败释放限额,避免用户还能收款 - auto_id = (getattr(audit, 'tixian_auto_id', None) or '').strip() - 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() - ) + auto = _lock_auto_record_by_audit(audit) if auto is not None and int(auto.zhuangtai) == 0: _close_auto_record_failed(auto, reason) @@ -1419,7 +1442,7 @@ def admin_reject_pending_or_auditing( sync_audit_and_jilu_status( audit, 5, bhliyou=reason, - bo_hui_ren_id=kefu_uid or '', + bo_hui_ren_id=kefu_uid or None, tixian_auto_id=None, ) tixian.shenheid = kefu_uid or tixian.shenheid or '' @@ -1437,7 +1460,7 @@ def admin_reject_pending_or_auditing( shouxufei=audit.shouxufei, refund_fee=bool(refund_fee), 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}', ) return refund_result diff --git a/users/views/kefu_withdraw.py b/users/views/kefu_withdraw.py index ef28b36..436829c 100644 --- a/users/views/kefu_withdraw.py +++ b/users/views/kefu_withdraw.py @@ -728,7 +728,10 @@ class KefuWithdrawActionView(APIView): # action=2:审核中/待收款 → 驳回 if action == 2: 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( audit, tixian, user, kefu_uid, reason, refund_principal=refund_principal, @@ -902,6 +905,7 @@ class KefuWithdrawActionView(APIView): ) 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) except Exception as e: logger.error(f'处理提现事务失败: {e}', exc_info=True)