feat(huya): 协作台账状态机新口径(跳步/已确认绑定/兑换失败)+ 账号全生命周期快照(迁移 0059)

This commit is contained in:
yml2213
2026-10-16 22:00:34 +08:00
parent aac264b639
commit e8abd60734
11 changed files with 1897 additions and 84 deletions
+115 -2
View File
@@ -26,9 +26,13 @@ from ...models import AuditLog, HuyaExternalOrder, User
from ...schemas import (
HuyaCollabCkPreviewOut,
HuyaCollabCkPreviewRequest,
HuyaCollabMetricOut,
HuyaCollabShopCreate,
HuyaCollabShopOut,
HuyaCollabShopUpdate,
HuyaExternalOrderActivityItemOut,
HuyaExternalOrderActivityQueryOut,
HuyaExternalOrderActivityQueryRequest,
HuyaExternalOrderAuditOut,
HuyaExternalOrderCkRequest,
HuyaExternalOrderCkStatusRequest,
@@ -38,6 +42,8 @@ from ...schemas import (
HuyaExternalOrderListOut,
HuyaExternalOrderOut,
HuyaExternalOrderOwnerOut,
HuyaExternalOrderStatusBatchOut,
HuyaExternalOrderStatusBatchRequest,
HuyaExternalOrderStatusRequest,
HuyaExternalOrderSummaryOut,
HuyaExternalOrderUpdate,
@@ -58,10 +64,12 @@ def _http_error(exc: collab.CollabError) -> HTTPException:
def _serialize_one(db: Session, order: HuyaExternalOrder) -> dict:
clusters = collab.buyer_clusters(db, [order])
metrics = collab.latest_metrics(db, [order])
return collab.serialize_order(
order,
users=collab.users_by_id(db, [order]),
buyer_cluster=clusters.get(int(order.id)),
last_metric=metrics.get(int(order.id)),
)
@@ -200,12 +208,16 @@ def list_external_orders(
page_size=page_size,
)
names = collab.users_by_id(db, rows)
# 「同一买家的其它单」整页一次算完(按绑定账号 + 绑定角色软识别,只读派生)
# 「同一买家的其它单」+「最近一次积分/兑换快照」整页一次算完,别按行发 SQL
clusters = collab.buyer_clusters(db, rows)
metrics = collab.latest_metrics(db, rows)
return {
"items": [
collab.serialize_order(
row, users=names, buyer_cluster=clusters.get(int(row.id))
row,
users=names,
buyer_cluster=clusters.get(int(row.id)),
last_metric=metrics.get(int(row.id)),
)
for row in rows
],
@@ -289,6 +301,62 @@ def preview_external_order_ck(
return preview
@router.post(
"/external-orders/status/batch", response_model=HuyaExternalOrderStatusBatchOut
)
def batch_update_external_order_status(
req: HuyaExternalOrderStatusBatchRequest,
db: Session = Depends(get_db),
current: User = Depends(require_permission("huya:collab:edit")),
):
"""勾选多行一次改业务状态(单个也走这里)。
人工切换允许**往前跳步**(待处理 → 已上脚本),回退要带 ``rollback=true``;
某一行前置校验没过(如没主页截图不能进「已确认绑定」)只记在这一条的 ``message`` 里。
"""
try:
orders = collab.list_orders_by_ids(db, req.ids)
result = collab.set_status_batch(
db,
current,
orders,
req.status,
reason=req.reason,
rollback=req.rollback,
)
except collab.CollabError as exc:
raise _http_error(exc) from exc
result["target_label"] = collab.ORDER_STATUS_LABELS.get(req.status, req.status)
return result
@router.post(
"/external-orders/activity/query", response_model=HuyaExternalOrderActivityQueryOut
)
def batch_query_external_order_activity(
req: HuyaExternalOrderActivityQueryRequest,
db: Session = Depends(get_db),
current: User = Depends(require_permission("huya:collab:edit")),
):
"""勾选多行查询积分 + 兑换记录(**串行带间隔**,防风控)。
每行都会落一条生命周期快照;「已上脚本」的单按查询结果自动改状态
(查到礼包 → 已完成;没查到 → 兑换失败),其它状态只记录不动状态。
"""
try:
orders = collab.list_orders_by_ids(db, req.ids)
result = collab.query_activity_batch(db, current, orders)
except collab.CollabError as exc:
raise _http_error(exc) from exc
for item in result["results"]:
item["status_label"] = collab.ORDER_STATUS_LABELS.get(
item.get("status", ""), item.get("status", "")
)
auto = item.get("auto_status") or ""
item["auto_status_label"] = collab.ORDER_STATUS_LABELS.get(auto, auto)
return result
@router.post("/external-orders/ck/verify", response_model=HuyaExternalOrderVerifyOut)
def verify_external_orders_ck(
req: HuyaExternalOrderVerifyRequest,
@@ -399,6 +467,51 @@ def update_external_order_status(
return _serialize_one(db, order)
@router.post(
"/external-orders/{order_id}/activity/query",
response_model=HuyaExternalOrderActivityItemOut,
)
def query_external_order_activity(
order_id: int,
db: Session = Depends(get_db),
current: User = Depends(require_permission("huya:collab:edit")),
):
"""查这一单的积分 + 兑换记录(单行「查询」按钮):写一条生命周期快照。
「已上脚本」的单按查询结果自动改状态:查到这一单的礼包 → 已完成;
接口通了但没查到 → 兑换失败;接口没通 → 不动(数据不够不许瞎判)。
"""
try:
order = collab.get_order(db, order_id)
result = collab.query_order_activity(db, current, order)
except collab.CollabError as exc:
raise _http_error(exc) from exc
result["status_label"] = collab.ORDER_STATUS_LABELS.get(
result.get("status", ""), result.get("status", "")
)
auto = result.get("auto_status") or ""
result["auto_status_label"] = collab.ORDER_STATUS_LABELS.get(auto, auto)
return result
@router.get(
"/external-orders/{order_id}/metrics", response_model=list[HuyaCollabMetricOut]
)
def list_external_order_metrics(
order_id: int,
db: Session = Depends(get_db),
_current: User = Depends(require_permission("huya:collab:view")),
):
"""这一单的「账号全生命周期」时间线:每次查积分/兑换记录的快照(新→旧)。"""
try:
order = collab.get_order(db, order_id)
except collab.CollabError as exc:
raise _http_error(exc) from exc
rows = collab.list_metrics(db, order)
names = collab.user_names(db, [row.created_by for row in rows])
return [collab.serialize_metric(row, users=names) for row in rows]
@router.post("/external-orders/{order_id}/ck", response_model=HuyaExternalOrderOut)
def update_external_order_ck(
order_id: int,