From 708e454959b91b97b52583d63431a116a1557dcb Mon Sep 17 00:00:00 2001 From: guke Date: Thu, 16 Jul 2026 18:34:07 +0800 Subject: [PATCH] =?UTF-8?q?feat(welfare):=20=E8=BF=81=E7=A7=BB=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20inactivity=5Freset=5Flog=20/=20inactivity=5Fnotific?= =?UTF-8?q?ation=5Flog=20=E4=B8=A4=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- .../135e79414fd0_add_inactivity_tables.py | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 alembic/versions/135e79414fd0_add_inactivity_tables.py diff --git a/alembic/versions/135e79414fd0_add_inactivity_tables.py b/alembic/versions/135e79414fd0_add_inactivity_tables.py new file mode 100644 index 0000000..e522bae --- /dev/null +++ b/alembic/versions/135e79414fd0_add_inactivity_tables.py @@ -0,0 +1,68 @@ +"""add inactivity tables + +Revision ID: 135e79414fd0 +Revises: comparison_llm_cost +Create Date: 2026-07-16 18:31:02.105929 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '135e79414fd0' +down_revision: Union[str, Sequence[str], None] = 'comparison_llm_cost' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + op.create_table( + "inactivity_reset_log", + sa.Column("id", sa.Integer(), autoincrement=True, nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.Column("coin_balance_before", sa.Integer(), nullable=False), + sa.Column("cash_balance_cents_before", sa.Integer(), nullable=False), + sa.Column("invite_cash_balance_cents_before", sa.Integer(), nullable=False), + sa.Column("last_active_at", sa.DateTime(timezone=True), nullable=True), + sa.Column("inactive_days", sa.Integer(), nullable=False), + sa.Column("reason", sa.String(length=32), nullable=False), + sa.Column("reset_at", sa.DateTime(timezone=True), + server_default=sa.text("(CURRENT_TIMESTAMP)"), nullable=False), + sa.PrimaryKeyConstraint("id"), + ) + with op.batch_alter_table("inactivity_reset_log", schema=None) as batch_op: + batch_op.create_index(batch_op.f("ix_inactivity_reset_log_user_id"), ["user_id"], unique=False) + batch_op.create_index(batch_op.f("ix_inactivity_reset_log_reset_at"), ["reset_at"], unique=False) + + op.create_table( + "inactivity_notification_log", + sa.Column("id", sa.Integer(), autoincrement=True, nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.Column("stage", sa.Integer(), nullable=False), + sa.Column("inactive_days", sa.Integer(), nullable=False), + sa.Column("coin_balance", sa.Integer(), nullable=False), + sa.Column("cash_balance_cents", sa.Integer(), nullable=False), + sa.Column("invite_cash_balance_cents", sa.Integer(), nullable=False), + sa.Column("channel", sa.String(length=16), nullable=False), + sa.Column("status", sa.String(length=16), nullable=False), + sa.Column("created_at", sa.DateTime(timezone=True), + server_default=sa.text("(CURRENT_TIMESTAMP)"), nullable=False), + sa.PrimaryKeyConstraint("id"), + ) + with op.batch_alter_table("inactivity_notification_log", schema=None) as batch_op: + batch_op.create_index(batch_op.f("ix_inactivity_notification_log_user_id"), ["user_id"], unique=False) + batch_op.create_index(batch_op.f("ix_inactivity_notification_log_created_at"), ["created_at"], unique=False) + + +def downgrade() -> None: + with op.batch_alter_table("inactivity_notification_log", schema=None) as batch_op: + batch_op.drop_index(batch_op.f("ix_inactivity_notification_log_created_at")) + batch_op.drop_index(batch_op.f("ix_inactivity_notification_log_user_id")) + op.drop_table("inactivity_notification_log") + with op.batch_alter_table("inactivity_reset_log", schema=None) as batch_op: + batch_op.drop_index(batch_op.f("ix_inactivity_reset_log_reset_at")) + batch_op.drop_index(batch_op.f("ix_inactivity_reset_log_user_id")) + op.drop_table("inactivity_reset_log")