feat(huya): 协作台账状态机新口径(跳步/已确认绑定/兑换失败)+ 账号全生命周期快照(迁移 0059)
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
"""新增 `huya_external_order_metrics`:账号全生命周期快照(积分 + 兑换记录)。
|
||||
|
||||
背景(2026-10-16 用户需求):抢购完成后要能查 `getUserScore`(积分)与
|
||||
`getUserPrizeRecords`(兑换记录),**每次查询都落一条快照** —— 这样"积分变化 + 兑换记录"
|
||||
两条线索合起来就能判断这一单到底兑换成功没有,而不是只看某一次的结果。
|
||||
|
||||
只追加、不更新;`verdict` 三态 success / failed / unknown;`raw` 存接口原始明细
|
||||
(里面**没有凭据**)。订单被删时这些快照跟着删(外键 CASCADE)。
|
||||
|
||||
可重复执行:表已存在就直接返回。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Sequence
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
revision: str = "20261016_0059"
|
||||
down_revision: str | None = "20261016_0058"
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
TABLE = "huya_external_order_metrics"
|
||||
ORDERS = "huya_external_orders"
|
||||
USERS = "users"
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
bind = op.get_bind()
|
||||
if TABLE in set(sa.inspect(bind).get_table_names()):
|
||||
return
|
||||
op.create_table(
|
||||
TABLE,
|
||||
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
|
||||
sa.Column("order_id", sa.Integer(), nullable=False),
|
||||
sa.Column("order_no", sa.String(length=64), nullable=False, server_default=""),
|
||||
sa.Column("uid", sa.String(length=32), nullable=False, server_default=""),
|
||||
sa.Column("sid", sa.Integer(), nullable=True),
|
||||
sa.Column("score", sa.Integer(), nullable=True),
|
||||
sa.Column("gained_score", sa.Integer(), nullable=True),
|
||||
sa.Column("used_score", sa.Integer(), nullable=True),
|
||||
sa.Column("records_total", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("records_matched", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column(
|
||||
"verdict", sa.String(length=16), nullable=False, server_default="unknown"
|
||||
),
|
||||
sa.Column("message", sa.String(length=512), nullable=False, server_default=""),
|
||||
sa.Column(
|
||||
"source", sa.String(length=16), nullable=False, server_default="manual"
|
||||
),
|
||||
sa.Column("raw", sa.JSON(), nullable=True),
|
||||
sa.Column("created_by", sa.Integer(), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(
|
||||
["order_id"],
|
||||
[f"{ORDERS}.id"],
|
||||
name=f"fk_{TABLE}_order_id",
|
||||
ondelete="CASCADE",
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
["created_by"], [f"{USERS}.id"], name=f"fk_{TABLE}_created_by"
|
||||
),
|
||||
)
|
||||
op.create_index(f"ix_{TABLE}_order_id", TABLE, ["order_id"])
|
||||
op.create_index(f"ix_{TABLE}_uid", TABLE, ["uid"])
|
||||
op.create_index(f"ix_{TABLE}_verdict", TABLE, ["verdict"])
|
||||
op.create_index(f"ix_{TABLE}_created_at", TABLE, ["created_at"])
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
bind = op.get_bind()
|
||||
if TABLE in set(sa.inspect(bind).get_table_names()):
|
||||
# MySQL 删表会连索引一起删。
|
||||
op.drop_table(TABLE)
|
||||
Reference in New Issue
Block a user