feat: 完善周期报告与用户行为分析
- 支持可配置周报月报模板与登录后异步补生成\n- 增加用户行为埋点和后台分析页面\n- 移除主题额度并保留实修回顾结算\n- 修复历史会话续聊上下文丢失
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
"""remove monthly topic quota while preserving practice review data
|
||||
|
||||
Revision ID: 0036_remove_topic_quota
|
||||
Revises: 0035_content_gen_variables
|
||||
"""
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
|
||||
revision = "0036_remove_topic_quota"
|
||||
down_revision = "0035_content_gen_variables"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
OLD_REVIEW_KEY = "topic_auto_settle_successful_rounds"
|
||||
NEW_REVIEW_KEY = "practice_review_auto_settle_successful_rounds"
|
||||
|
||||
|
||||
def _rename_config_key(old_key: str, new_key: str) -> None:
|
||||
connection = op.get_bind()
|
||||
old_exists = connection.execute(
|
||||
sa.text("SELECT COUNT(*) FROM sys_system_config WHERE config_key = :key"),
|
||||
{"key": old_key},
|
||||
).scalar()
|
||||
if not old_exists:
|
||||
return
|
||||
new_exists = connection.execute(
|
||||
sa.text("SELECT COUNT(*) FROM sys_system_config WHERE config_key = :key"),
|
||||
{"key": new_key},
|
||||
).scalar()
|
||||
if new_exists:
|
||||
connection.execute(
|
||||
sa.text("DELETE FROM sys_system_config WHERE config_key = :key"),
|
||||
{"key": old_key},
|
||||
)
|
||||
return
|
||||
connection.execute(
|
||||
sa.text("UPDATE sys_system_config SET config_key = :new_key WHERE config_key = :old_key"),
|
||||
{"new_key": new_key, "old_key": old_key},
|
||||
)
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
_rename_config_key(OLD_REVIEW_KEY, NEW_REVIEW_KEY)
|
||||
op.drop_column("sys_entitlement_plan", "deduct_quota")
|
||||
op.drop_column("sys_entitlement_plan", "monthly_topic_limit")
|
||||
op.drop_column("sys_topic_session", "quota_deducted")
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.add_column(
|
||||
"sys_topic_session",
|
||||
sa.Column("quota_deducted", sa.Integer(), nullable=False, server_default="0"),
|
||||
)
|
||||
op.add_column(
|
||||
"sys_entitlement_plan",
|
||||
sa.Column("monthly_topic_limit", sa.Integer(), nullable=True),
|
||||
)
|
||||
op.add_column(
|
||||
"sys_entitlement_plan",
|
||||
sa.Column("deduct_quota", sa.Integer(), nullable=False, server_default="1"),
|
||||
)
|
||||
_rename_config_key(NEW_REVIEW_KEY, OLD_REVIEW_KEY)
|
||||
@@ -0,0 +1,38 @@
|
||||
"""track chat and weekly-report sources for configurable periodic reports
|
||||
|
||||
Revision ID: 0037_report_sources
|
||||
Revises: 0036_remove_topic_quota
|
||||
"""
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
|
||||
revision = "0037_report_sources"
|
||||
down_revision = "0036_remove_topic_quota"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column("sys_periodic_report", sa.Column("source_message_ids", sa.Text(), nullable=True))
|
||||
op.add_column("sys_periodic_report", sa.Column("source_report_ids", sa.Text(), nullable=True))
|
||||
op.alter_column(
|
||||
"sys_periodic_report",
|
||||
"schema_version",
|
||||
server_default="3",
|
||||
existing_type=sa.Integer(),
|
||||
existing_nullable=False,
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.alter_column(
|
||||
"sys_periodic_report",
|
||||
"schema_version",
|
||||
server_default="2",
|
||||
existing_type=sa.Integer(),
|
||||
existing_nullable=False,
|
||||
)
|
||||
op.drop_column("sys_periodic_report", "source_report_ids")
|
||||
op.drop_column("sys_periodic_report", "source_message_ids")
|
||||
@@ -0,0 +1,42 @@
|
||||
"""add user behavior analytics
|
||||
|
||||
Revision ID: 0038_user_behavior
|
||||
Revises: 0037_report_sources
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
revision = "0038_user_behavior"
|
||||
down_revision = "0037_report_sources"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.create_table(
|
||||
"sys_user_behavior_event",
|
||||
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column("client_event_id", sa.String(length=36), nullable=False),
|
||||
sa.Column("user_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("event_code", sa.String(length=64), nullable=False),
|
||||
sa.Column("event_name", sa.String(length=100), nullable=False),
|
||||
sa.Column("event_type", sa.String(length=20), nullable=False),
|
||||
sa.Column("target_type", sa.String(length=30), nullable=True),
|
||||
sa.Column("target_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("occurred_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("created_at", sa.DateTime(), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=False),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint("client_event_id", name="uq_user_behavior_client_event"),
|
||||
)
|
||||
op.create_index("ix_user_behavior_occurred", "sys_user_behavior_event", ["occurred_at", "id"])
|
||||
op.create_index("ix_user_behavior_user_occurred", "sys_user_behavior_event", ["user_id", "occurred_at", "id"])
|
||||
op.create_index("ix_user_behavior_code_occurred", "sys_user_behavior_event", ["event_code", "occurred_at", "id"])
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index("ix_user_behavior_code_occurred", table_name="sys_user_behavior_event")
|
||||
op.drop_index("ix_user_behavior_user_occurred", table_name="sys_user_behavior_event")
|
||||
op.drop_index("ix_user_behavior_occurred", table_name="sys_user_behavior_event")
|
||||
op.drop_table("sys_user_behavior_event")
|
||||
Reference in New Issue
Block a user