fix: 充值核账按绑定账号和角色整组
This commit is contained in:
@@ -777,7 +777,7 @@ def set_status_batch(
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 充值核账(按 bind_game_account 整组)
|
||||
# 充值核账(按「绑定账号 + 绑定角色」整组)
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
RECHARGE_GROUP_STATUSES: tuple[str, ...] = (
|
||||
@@ -786,12 +786,28 @@ RECHARGE_GROUP_STATUSES: tuple[str, ...] = (
|
||||
STATUS_POINTS_ERROR,
|
||||
)
|
||||
|
||||
# 探针读到的 bind_game_account 往往是「微信用户 / QQ用户」这种通用昵称,
|
||||
# 只按它分组会把不同买家并成一组(2026-10-19 生产 8 单被合成 48000 分)。
|
||||
# 与「同一买家」软识别保持一致:账号 + 角色才是可用的买家指纹。
|
||||
RechargeGroupKey = tuple[str, str]
|
||||
|
||||
def _recharge_group_orders(db: Session, group_key: str) -> list[HuyaExternalOrder]:
|
||||
|
||||
def _recharge_group_key(order: HuyaExternalOrder) -> RechargeGroupKey | None:
|
||||
return buyer_key_of(order)
|
||||
|
||||
|
||||
def _recharge_group_label(group_key: RechargeGroupKey) -> str:
|
||||
return f"{group_key[0]} / {group_key[1]}"
|
||||
|
||||
|
||||
def _recharge_group_orders(
|
||||
db: Session, group_key: RechargeGroupKey
|
||||
) -> list[HuyaExternalOrder]:
|
||||
return (
|
||||
db.query(HuyaExternalOrder)
|
||||
.filter(
|
||||
HuyaExternalOrder.bind_game_account == group_key,
|
||||
HuyaExternalOrder.bind_game_account == group_key[0],
|
||||
HuyaExternalOrder.bind_game_role == group_key[1],
|
||||
HuyaExternalOrder.status.in_(RECHARGE_GROUP_STATUSES),
|
||||
)
|
||||
.order_by(HuyaExternalOrder.id.asc())
|
||||
@@ -866,23 +882,21 @@ def _resolve_group_required_points(
|
||||
def _check_recharge_group(
|
||||
db: Session,
|
||||
current: User | None,
|
||||
group_key: str,
|
||||
group_key: RechargeGroupKey,
|
||||
*,
|
||||
threshold: int,
|
||||
client: Any | None = None,
|
||||
) -> dict:
|
||||
group_label = _recharge_group_label(group_key)
|
||||
group_orders = _recharge_group_orders(db, group_key)
|
||||
if not group_orders:
|
||||
raise CollabError(
|
||||
f"绑定账号「{group_key}」下没有可核账的订单",
|
||||
f"绑定账号「{group_label}」下没有可核账的订单",
|
||||
code="recharge_group_empty",
|
||||
)
|
||||
if any(
|
||||
str(order.bind_game_account or "").strip() != group_key
|
||||
for order in group_orders
|
||||
):
|
||||
if any(_recharge_group_key(order) != group_key for order in group_orders):
|
||||
raise CollabError(
|
||||
"核账过程中绑定账号发生变化,请刷新后重试",
|
||||
"核账过程中绑定账号/角色发生变化,请刷新后重试",
|
||||
code="bind_account_changed",
|
||||
)
|
||||
|
||||
@@ -916,9 +930,9 @@ def _check_recharge_group(
|
||||
f"{order.order_no} 的 CK 验证失败:{result.get('message') or '未知原因'}",
|
||||
code="ck_invalid",
|
||||
)
|
||||
if str(order.bind_game_account or "").strip() != group_key:
|
||||
if _recharge_group_key(order) != group_key:
|
||||
raise CollabError(
|
||||
"核账过程中探针读到的绑定账号发生变化,请刷新后重试",
|
||||
"核账过程中探针读到的绑定账号/角色发生变化,请刷新后重试",
|
||||
code="bind_account_changed",
|
||||
)
|
||||
|
||||
@@ -979,7 +993,9 @@ def _check_recharge_group(
|
||||
|
||||
now = _now()
|
||||
detail = {
|
||||
"group_key": group_key,
|
||||
"group_key": group_label,
|
||||
"bind_game_account": group_key[0],
|
||||
"bind_game_role": group_key[1],
|
||||
"threshold": threshold,
|
||||
"balance": balance,
|
||||
"required_total": required_total,
|
||||
@@ -1033,7 +1049,9 @@ def _check_recharge_group(
|
||||
target=_audit_target(order),
|
||||
detail={
|
||||
"order_no": order.order_no,
|
||||
"group_key": group_key,
|
||||
"group_key": group_label,
|
||||
"bind_game_account": group_key[0],
|
||||
"bind_game_role": group_key[1],
|
||||
"status": result_status,
|
||||
"balance": balance,
|
||||
"required_total": required_total,
|
||||
@@ -1045,7 +1063,7 @@ def _check_recharge_group(
|
||||
)
|
||||
|
||||
return {
|
||||
"group_key": group_key,
|
||||
"group_key": group_label,
|
||||
"status": result_status,
|
||||
"status_label": ORDER_STATUS_LABELS.get(result_status, result_status),
|
||||
"balance": balance,
|
||||
@@ -1076,10 +1094,12 @@ def check_recharge_groups(
|
||||
client: Any | None = None,
|
||||
commit: bool = True,
|
||||
) -> dict:
|
||||
"""按 ``bind_game_account`` 整组核账,并整组落到「已充值 / 积分异常」。
|
||||
"""按「``bind_game_account`` + ``bind_game_role``」整组核账,并整组落到「已充值 / 积分异常」。
|
||||
|
||||
规则(2026-10-19 用户拍板):
|
||||
规则(2026-10-19 用户拍板,随后按生产数据修正分组键):
|
||||
|
||||
- 分组键必须是**账号 + 角色**:探针读到的账号经常是「微信用户 / QQ用户」这种
|
||||
通用昵称,只按账号会把不同买家并成一组(生产 8 单被合成 48000 分);
|
||||
- 只统计同组 ``to_recharge / recharged / points_error`` 的订单;
|
||||
- 组内不同 uid 的 CK 各查一次积分,合计为“账号积分”;
|
||||
- ``结余 = 账号积分合计 - 礼包积分合计``;
|
||||
@@ -1097,18 +1117,18 @@ def check_recharge_groups(
|
||||
)
|
||||
threshold_value = normalize_points_threshold(threshold)
|
||||
|
||||
group_keys: list[str] = []
|
||||
group_keys: list[RechargeGroupKey] = []
|
||||
failures: list[dict] = []
|
||||
failed_order_count = 0
|
||||
for order in rows:
|
||||
key = str(order.bind_game_account or "").strip()
|
||||
if not key:
|
||||
key = _recharge_group_key(order)
|
||||
if key is None:
|
||||
_maybe_demote_missing_data(db, current, order)
|
||||
failures.append(
|
||||
{
|
||||
"id": int(order.id),
|
||||
"order_no": order.order_no,
|
||||
"message": "缺少绑定账号,已保持/退回「待补资料」",
|
||||
"message": "缺少绑定账号或绑定角色,已保持/退回「待补资料」",
|
||||
}
|
||||
)
|
||||
failed_order_count += 1
|
||||
@@ -1118,6 +1138,7 @@ def check_recharge_groups(
|
||||
|
||||
groups: list[dict] = []
|
||||
for key in group_keys:
|
||||
group_label = _recharge_group_label(key)
|
||||
try:
|
||||
with db.begin_nested():
|
||||
group = _check_recharge_group(
|
||||
@@ -1133,7 +1154,7 @@ def check_recharge_groups(
|
||||
failed_order_count += max(1, len(group_rows))
|
||||
groups.append(
|
||||
{
|
||||
"group_key": key,
|
||||
"group_key": group_label,
|
||||
"status": "",
|
||||
"status_label": "",
|
||||
"balance": None,
|
||||
@@ -1152,7 +1173,7 @@ def check_recharge_groups(
|
||||
failed_order_count += max(1, len(group_rows))
|
||||
groups.append(
|
||||
{
|
||||
"group_key": key,
|
||||
"group_key": group_label,
|
||||
"status": "",
|
||||
"status_label": "",
|
||||
"balance": None,
|
||||
|
||||
@@ -585,7 +585,7 @@ export default function HuyaCollabPage() {
|
||||
const [batchStatusTarget, setBatchStatusTarget] = useState<HuyaCollabStatus>('to_recharge');
|
||||
const [batchStatusReason, setBatchStatusReason] = useState('');
|
||||
const [batchStatusRollback, setBatchStatusRollback] = useState(false);
|
||||
// 充值核账弹窗:按 bind_game_account 整组核账,阈值默认 100
|
||||
// 充值核账弹窗:按「绑定账号 + 绑定角色」整组核账,阈值默认 100
|
||||
const [rechargeOpen, setRechargeOpen] = useState(false);
|
||||
const [rechargeIds, setRechargeIds] = useState<number[]>([]);
|
||||
const [rechargeThreshold, setRechargeThreshold] = useState(readRechargeThreshold);
|
||||
@@ -2488,7 +2488,7 @@ export default function HuyaCollabPage() {
|
||||
</Dropdown>
|
||||
)}
|
||||
{canEdit && !isArchiveView && (
|
||||
<Tooltip title="按绑定账号整组校验 CK 和积分,整组落到「已充值 / 积分异常」">
|
||||
<Tooltip title="按「绑定账号 + 绑定角色」整组校验 CK 和积分,整组落到「已充值 / 积分异常」">
|
||||
<Button icon={<AuditOutlined />} disabled={selectedIds.length === 0 || busy}
|
||||
onClick={() => openRecharge(selectedIds)}>
|
||||
充值核账{selectedIds.length > 0 ? `(${selectedIds.length})` : ''}
|
||||
@@ -3399,8 +3399,8 @@ export default function HuyaCollabPage() {
|
||||
<Alert
|
||||
type="info"
|
||||
showIcon
|
||||
message="按绑定账号整组核账"
|
||||
description="同一 bind_game_account 下的待充值/已充值/积分异常订单会一起核账;CK 失效或积分查不到时整组保持原状态。"
|
||||
message="按「绑定账号 + 绑定角色」整组核账"
|
||||
description="同一绑定账号和角色下的待充值/已充值/积分异常订单会一起核账;CK 失效或积分查不到时整组保持原状态。"
|
||||
/>
|
||||
<Space size={8} align="center">
|
||||
<Text>允许结余阈值</Text>
|
||||
|
||||
Reference in New Issue
Block a user