fix(huya): 作废订单后失效旧积分快照

This commit is contained in:
yml
2026-11-12 16:08:13 +08:00
parent 2ae90ef78f
commit 56e5d0ea1c
6 changed files with 438 additions and 2 deletions
+106
View File
@@ -730,6 +730,14 @@ def set_status(
"allow_recharge": bool(allow_recharge),
},
)
if target == STATUS_VOID or from_status == STATUS_VOID:
_invalidate_recharge_group_after_void(
db,
current,
order,
changed_from=from_status,
changed_to=target,
)
if commit:
db.commit()
db.refresh(order)
@@ -827,6 +835,17 @@ RECHARGE_GROUP_STATUSES: tuple[str, ...] = (
STATUS_RECHARGED,
STATUS_POINTS_ERROR,
)
_POINTS_SNAPSHOT_FIELDS: tuple[str, ...] = (
"points_checked_at",
"points_balance",
"points_required_total",
"points_surplus",
"points_threshold",
"points_check_reason",
"points_check_message",
"points_check_detail",
)
_STALE_RECHARGE_MESSAGE = "订单组成员已作废或恢复,原积分统计已失效,请重新核账"
# 探针读到的 bind_game_account 往往是「微信用户 / QQ用户」这种通用昵称,
# 只按它分组会把不同买家并成一组(2026-10-19 生产 8 单被合成 48000 分)。
@@ -857,6 +876,93 @@ def _recharge_group_orders(
)
def _clear_points_snapshot(order: HuyaExternalOrder) -> None:
order.points_checked_at = None
order.points_balance = None
order.points_required_total = None
order.points_surplus = None
order.points_threshold = None
order.points_check_reason = ""
order.points_check_message = ""
order.points_check_detail = None
def _invalidate_recharge_group_after_void(
db: Session,
current: User | None,
changed_order: HuyaExternalOrder,
*,
changed_from: str,
changed_to: str,
) -> None:
"""订单作废/恢复后,让同组旧核账结果失效,避免继续展示作废前的合计。"""
group_key = buyer_key_of(changed_order)
if group_key is None:
return
rows = (
db.query(HuyaExternalOrder)
.filter(
HuyaExternalOrder.bind_game_account == group_key[0],
HuyaExternalOrder.bind_game_role == group_key[1],
or_(
HuyaExternalOrder.id == changed_order.id,
HuyaExternalOrder.status.in_(RECHARGE_GROUP_STATUSES),
),
)
.order_by(HuyaExternalOrder.id.asc())
.all()
)
now = _now()
for row in rows:
previous_status = row.status
previous_snapshot = {
field: getattr(row, field)
for field in (
"points_checked_at",
"points_balance",
"points_required_total",
"points_surplus",
)
}
had_snapshot = any(
getattr(row, field) not in (None, "") for field in _POINTS_SNAPSHOT_FIELDS
)
next_status = previous_status
if (
row.id != changed_order.id
and previous_status in (STATUS_RECHARGED, STATUS_POINTS_ERROR)
and had_snapshot
and _is_ready_for_recharge(row)
):
next_status = STATUS_TO_RECHARGE
row.status = next_status
if row.bound_at is None:
row.bound_at = now
_sync_stage_timestamps(row, next_status, now)
if not had_snapshot and next_status == previous_status:
continue
_clear_points_snapshot(row)
row.points_check_reason = "stale_group"
row.points_check_message = _STALE_RECHARGE_MESSAGE
_touch(row, current)
record_audit(
db,
current,
action="huya:collab:recharge_invalidate",
target=_audit_target(row),
detail={
"source_order_no": changed_order.order_no,
"source_change": f"{changed_from}->{changed_to}",
"group_key": _recharge_group_label(group_key),
"from_status": previous_status,
"to_status": next_status,
"previous": previous_snapshot,
},
)
def _resolve_group_required_points(
db: Session,
current: User | None,