93 lines
3.2 KiB
Python
93 lines
3.2 KiB
Python
"""订阅实例业务流水号
|
|
|
|
Revision ID: 20260814_subscription_no
|
|
Revises: 20260814_restore_renewal
|
|
Create Date: 2026-08-14 14:23:00
|
|
|
|
说明:
|
|
- 每张 user_credit_subscriptions 增加永久唯一 subscription_no。
|
|
- 个人订阅前缀 PS,团队订阅前缀 TS。
|
|
- 全局共用 PostgreSQL Sequence,避免 COUNT/MAX 并发冲突。
|
|
- 历史记录按原 created_at 日期生成业务编号;编号只用于展示/客服定位,不参与业务排序和结算。
|
|
"""
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
|
|
revision = "20260814_subscription_no"
|
|
down_revision = "20260814_restore_renewal"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def _columns(table_name: str) -> set[str]:
|
|
inspector = sa.inspect(op.get_bind())
|
|
if table_name not in inspector.get_table_names():
|
|
return set()
|
|
return {item["name"] for item in inspector.get_columns(table_name)}
|
|
|
|
|
|
def _indexes(table_name: str) -> set[str]:
|
|
inspector = sa.inspect(op.get_bind())
|
|
if table_name not in inspector.get_table_names():
|
|
return set()
|
|
return {item["name"] for item in inspector.get_indexes(table_name)}
|
|
|
|
|
|
def upgrade() -> None:
|
|
bind = op.get_bind()
|
|
if bind.dialect.name != "postgresql":
|
|
raise RuntimeError("订阅实例流水号迁移当前仅支持 PostgreSQL")
|
|
|
|
op.execute("CREATE SEQUENCE IF NOT EXISTS credit_subscription_no_seq START WITH 1 INCREMENT BY 1")
|
|
|
|
if "subscription_no" not in _columns("user_credit_subscriptions"):
|
|
op.add_column(
|
|
"user_credit_subscriptions",
|
|
sa.Column(
|
|
"subscription_no",
|
|
sa.String(length=32),
|
|
nullable=True,
|
|
comment="订阅业务实例编号,供用户/客服/开发定位",
|
|
),
|
|
)
|
|
|
|
# 历史数据一次性补号。日期使用东八区业务日期;Sequence 只保证唯一,不要求无跳号。
|
|
op.execute(
|
|
"""
|
|
UPDATE user_credit_subscriptions
|
|
SET subscription_no =
|
|
CASE
|
|
WHEN product_type_snapshot = 'team_subscription' THEN 'TS'
|
|
ELSE 'PS'
|
|
END
|
|
|| to_char(COALESCE(created_at, start_at, now()) AT TIME ZONE 'Asia/Shanghai', 'YYYYMMDD')
|
|
|| lpad(nextval('credit_subscription_no_seq')::text, 6, '0')
|
|
WHERE subscription_no IS NULL OR btrim(subscription_no) = ''
|
|
"""
|
|
)
|
|
|
|
op.alter_column(
|
|
"user_credit_subscriptions",
|
|
"subscription_no",
|
|
existing_type=sa.String(length=32),
|
|
nullable=False,
|
|
)
|
|
|
|
if "uq_user_credit_subscriptions_no" not in _indexes("user_credit_subscriptions"):
|
|
op.create_index(
|
|
"uq_user_credit_subscriptions_no",
|
|
"user_credit_subscriptions",
|
|
["subscription_no"],
|
|
unique=True,
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
if "uq_user_credit_subscriptions_no" in _indexes("user_credit_subscriptions"):
|
|
op.drop_index("uq_user_credit_subscriptions_no", table_name="user_credit_subscriptions")
|
|
if "subscription_no" in _columns("user_credit_subscriptions"):
|
|
op.drop_column("user_credit_subscriptions", "subscription_no")
|
|
op.execute("DROP SEQUENCE IF EXISTS credit_subscription_no_seq")
|