feat: add entitlement plans and topic sessions
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
"""add entitlement plans and topic sessions
|
||||
|
||||
Revision ID: 0014_entitlements_topics
|
||||
Revises: 0013_question_insight_indexes
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
revision = "0014_entitlements_topics"
|
||||
down_revision = "0013_question_insight_indexes"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
PRIMARY_KEY_TYPE = sa.BigInteger().with_variant(sa.Integer(), "sqlite")
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
inspector = sa.inspect(op.get_bind())
|
||||
tables = set(inspector.get_table_names())
|
||||
if "sys_entitlement_plan" not in tables:
|
||||
op.create_table(
|
||||
"sys_entitlement_plan",
|
||||
sa.Column("id", PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True),
|
||||
sa.Column("name", sa.String(80), nullable=False),
|
||||
sa.Column("plan_type", sa.String(30), nullable=False),
|
||||
sa.Column("description", sa.String(255), nullable=True),
|
||||
sa.Column("validity_days", sa.Integer(), nullable=True),
|
||||
sa.Column("monthly_topic_limit", sa.Integer(), nullable=True),
|
||||
sa.Column("enable_growth_profile", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("enable_periodic_reports", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("allow_help_card", sa.Integer(), nullable=False, server_default="1"),
|
||||
sa.Column("allow_share_draft", sa.Integer(), nullable=False, server_default="1"),
|
||||
sa.Column("deduct_quota", sa.Integer(), nullable=False, server_default="1"),
|
||||
sa.Column("status", sa.Integer(), nullable=False, server_default="1"),
|
||||
sa.Column("sort_order", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
|
||||
sa.Column("updated_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
|
||||
)
|
||||
op.create_index("ix_sys_entitlement_plan_plan_type", "sys_entitlement_plan", ["plan_type"])
|
||||
op.create_index("ix_sys_entitlement_plan_status", "sys_entitlement_plan", ["status"])
|
||||
_seed_default_plans()
|
||||
|
||||
if "sys_user_entitlement" not in tables:
|
||||
op.create_table(
|
||||
"sys_user_entitlement",
|
||||
sa.Column("id", PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True),
|
||||
sa.Column("user_id", sa.BigInteger(), sa.ForeignKey("sys_user.id"), nullable=False),
|
||||
sa.Column("plan_id", sa.BigInteger(), sa.ForeignKey("sys_entitlement_plan.id"), nullable=False),
|
||||
sa.Column("status", sa.String(20), nullable=False, server_default="active"),
|
||||
sa.Column("effective_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("expired_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("assigned_by", sa.BigInteger(), nullable=True),
|
||||
sa.Column("remark", sa.String(255), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
|
||||
sa.Column("updated_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
|
||||
)
|
||||
op.create_index("ix_sys_user_entitlement_user_id", "sys_user_entitlement", ["user_id"])
|
||||
op.create_index("ix_sys_user_entitlement_plan_id", "sys_user_entitlement", ["plan_id"])
|
||||
op.create_index("ix_sys_user_entitlement_status", "sys_user_entitlement", ["status"])
|
||||
|
||||
if "sys_user_entitlement_log" not in tables:
|
||||
op.create_table(
|
||||
"sys_user_entitlement_log",
|
||||
sa.Column("id", PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True),
|
||||
sa.Column("user_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("entitlement_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("from_plan_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("to_plan_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("action", sa.String(30), nullable=False),
|
||||
sa.Column("detail_json", sa.Text(), nullable=True),
|
||||
sa.Column("operated_by", sa.BigInteger(), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
)
|
||||
op.create_index("ix_sys_user_entitlement_log_user_id", "sys_user_entitlement_log", ["user_id"])
|
||||
|
||||
if "sys_topic_session" not in tables:
|
||||
op.create_table(
|
||||
"sys_topic_session",
|
||||
sa.Column("id", PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True),
|
||||
sa.Column("user_id", sa.BigInteger(), sa.ForeignKey("sys_user.id"), nullable=False),
|
||||
sa.Column("chat_session_id", sa.BigInteger(), sa.ForeignKey("sys_chat_session.id"), nullable=False),
|
||||
sa.Column("title", sa.String(120), nullable=False),
|
||||
sa.Column("core_question", sa.Text(), nullable=False),
|
||||
sa.Column("status", sa.String(20), nullable=False, server_default="active"),
|
||||
sa.Column("message_count", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("token_input", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("token_output", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("quota_deducted", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("recommended_homework", sa.Text(), nullable=True),
|
||||
sa.Column("help_card_generated", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("share_draft_generated", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("started_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
|
||||
sa.Column("ended_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
|
||||
sa.Column("updated_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
|
||||
)
|
||||
op.create_index("ix_sys_topic_session_user_id", "sys_topic_session", ["user_id"])
|
||||
op.create_index("ix_sys_topic_session_chat_session_id", "sys_topic_session", ["chat_session_id"])
|
||||
op.create_index("ix_sys_topic_session_status", "sys_topic_session", ["status"])
|
||||
|
||||
columns = {column["name"] for column in inspector.get_columns("sys_chat_message")}
|
||||
if "topic_session_id" not in columns:
|
||||
op.add_column("sys_chat_message", sa.Column("topic_session_id", sa.BigInteger(), nullable=True))
|
||||
op.create_index("ix_sys_chat_message_topic_session_id", "sys_chat_message", ["topic_session_id"])
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
inspector = sa.inspect(op.get_bind())
|
||||
columns = {column["name"] for column in inspector.get_columns("sys_chat_message")}
|
||||
if "topic_session_id" in columns:
|
||||
op.drop_index("ix_sys_chat_message_topic_session_id", table_name="sys_chat_message")
|
||||
op.drop_column("sys_chat_message", "topic_session_id")
|
||||
tables = set(inspector.get_table_names())
|
||||
if "sys_topic_session" in tables:
|
||||
op.drop_index("ix_sys_topic_session_status", table_name="sys_topic_session")
|
||||
op.drop_index("ix_sys_topic_session_chat_session_id", table_name="sys_topic_session")
|
||||
op.drop_index("ix_sys_topic_session_user_id", table_name="sys_topic_session")
|
||||
op.drop_table("sys_topic_session")
|
||||
if "sys_user_entitlement_log" in tables:
|
||||
op.drop_index("ix_sys_user_entitlement_log_user_id", table_name="sys_user_entitlement_log")
|
||||
op.drop_table("sys_user_entitlement_log")
|
||||
if "sys_user_entitlement" in tables:
|
||||
op.drop_index("ix_sys_user_entitlement_status", table_name="sys_user_entitlement")
|
||||
op.drop_index("ix_sys_user_entitlement_plan_id", table_name="sys_user_entitlement")
|
||||
op.drop_index("ix_sys_user_entitlement_user_id", table_name="sys_user_entitlement")
|
||||
op.drop_table("sys_user_entitlement")
|
||||
if "sys_entitlement_plan" in tables:
|
||||
op.drop_index("ix_sys_entitlement_plan_status", table_name="sys_entitlement_plan")
|
||||
op.drop_index("ix_sys_entitlement_plan_plan_type", table_name="sys_entitlement_plan")
|
||||
op.drop_table("sys_entitlement_plan")
|
||||
|
||||
|
||||
def _seed_default_plans() -> None:
|
||||
op.bulk_insert(
|
||||
sa.table(
|
||||
"sys_entitlement_plan",
|
||||
sa.column("name"),
|
||||
sa.column("plan_type"),
|
||||
sa.column("description"),
|
||||
sa.column("validity_days"),
|
||||
sa.column("monthly_topic_limit"),
|
||||
sa.column("enable_growth_profile"),
|
||||
sa.column("enable_periodic_reports"),
|
||||
sa.column("allow_help_card"),
|
||||
sa.column("allow_share_draft"),
|
||||
sa.column("deduct_quota"),
|
||||
sa.column("status"),
|
||||
sa.column("sort_order"),
|
||||
),
|
||||
[
|
||||
{
|
||||
"name": "大本营基础版",
|
||||
"plan_type": "basic",
|
||||
"description": "随大本营提供,支持基础知识查询、功课方向和求助卡生成。",
|
||||
"validity_days": None,
|
||||
"monthly_topic_limit": 30,
|
||||
"enable_growth_profile": 0,
|
||||
"enable_periodic_reports": 0,
|
||||
"allow_help_card": 1,
|
||||
"allow_share_draft": 1,
|
||||
"deduct_quota": 1,
|
||||
"status": 1,
|
||||
"sort_order": 10,
|
||||
},
|
||||
{
|
||||
"name": "五个月深度陪伴版",
|
||||
"plan_type": "deep",
|
||||
"description": "支持长期成长档案、阶段报告和更高主题会话额度。",
|
||||
"validity_days": 150,
|
||||
"monthly_topic_limit": 90,
|
||||
"enable_growth_profile": 1,
|
||||
"enable_periodic_reports": 1,
|
||||
"allow_help_card": 1,
|
||||
"allow_share_draft": 1,
|
||||
"deduct_quota": 1,
|
||||
"status": 1,
|
||||
"sort_order": 20,
|
||||
},
|
||||
{
|
||||
"name": "高频加购包",
|
||||
"plan_type": "addon",
|
||||
"description": "用于少量高频用户补充主题会话额度。",
|
||||
"validity_days": 31,
|
||||
"monthly_topic_limit": 30,
|
||||
"enable_growth_profile": 0,
|
||||
"enable_periodic_reports": 0,
|
||||
"allow_help_card": 1,
|
||||
"allow_share_draft": 1,
|
||||
"deduct_quota": 1,
|
||||
"status": 1,
|
||||
"sort_order": 30,
|
||||
},
|
||||
{
|
||||
"name": "老师工作版",
|
||||
"plan_type": "teacher",
|
||||
"description": "内部老师使用,不消耗普通学员权益额度。",
|
||||
"validity_days": None,
|
||||
"monthly_topic_limit": None,
|
||||
"enable_growth_profile": 0,
|
||||
"enable_periodic_reports": 0,
|
||||
"allow_help_card": 1,
|
||||
"allow_share_draft": 1,
|
||||
"deduct_quota": 0,
|
||||
"status": 1,
|
||||
"sort_order": 40,
|
||||
},
|
||||
],
|
||||
)
|
||||
Reference in New Issue
Block a user