gitscope
← marzneshin / v0.7.2 / app/db/migrations/versions/20240627_a83e4dd22672_refactor_user_expire.py
https://dev.kronoz.win/r/marzneshin.git
app/db/migrations/versions/20240627_a83e4dd22672_refactor_user_expire.py · Python
Blame Raw
  1"""refactor user expire
  2
  3Revision ID: a83e4dd22672
  4Revises: 9001356f0063
  5Create Date: 2024-06-27 01:04:34.974520
  6
  7"""
  8
  9import sqlalchemy as sa
 10from alembic import op
 11from sqlalchemy import table, column
 12from sqlalchemy.dialects import postgresql
 13
 14# revision identifiers, used by Alembic.
 15revision = "a83e4dd22672"
 16down_revision = "9001356f0063"
 17branch_labels = None
 18depends_on = None
 19
 20
 21def upgrade() -> None:
 22    bind = op.get_bind()
 23    dialect = bind.dialect.name
 24
 25    if dialect == "postgresql":
 26        op.execute(
 27            """
 28            DO $$ 
 29            BEGIN 
 30                IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'userexpirestrategy') THEN
 31                    CREATE TYPE userexpirestrategy AS ENUM ('NEVER', 'FIXED_DATE', 'START_ON_FIRST_USE');
 32                END IF;
 33            END $$;
 34            """
 35        )
 36    op.add_column(
 37        "users",
 38        sa.Column(
 39            "activated",
 40            sa.Boolean(),
 41            nullable=False,
 42            server_default=sa.sql.true(),
 43        ),
 44    )
 45    op.add_column(
 46        "users",
 47        sa.Column(
 48            "expire_strategy",
 49            sa.Enum(
 50                "NEVER",
 51                "FIXED_DATE",
 52                "START_ON_FIRST_USE",
 53                name="userexpirestrategy",
 54            ),
 55            server_default="NEVER",
 56            nullable=False,
 57        ),
 58    )
 59
 60    if dialect == "sqlite":
 61        for old, new, type_ in [
 62            ("on_hold_timeout", "activation_deadline", sa.DateTime),
 63            ("expire", "expire_date", sa.DateTime),
 64            ("on_hold_expire_duration", "usage_duration", sa.Integer),
 65        ]:
 66            op.add_column("users", sa.Column(new, type_))
 67
 68            # Step 2: Copy data from the old column to the new column
 69            op.execute(f"UPDATE users SET {new} = {old}")
 70
 71            with op.batch_alter_table("users") as batch_op:
 72                batch_op.drop_column(old)
 73    else:
 74        op.alter_column(
 75            "users",
 76            "on_hold_timeout",
 77            new_column_name="activation_deadline",
 78            existing_type=sa.DateTime,
 79        )
 80        op.alter_column(
 81            "users",
 82            "expire",
 83            new_column_name="expire_date",
 84            existing_type=sa.DateTime,
 85        )
 86        op.alter_column(
 87            "users",
 88            "on_hold_expire_duration",
 89            new_column_name="usage_duration",
 90            existing_type=sa.BigInteger,
 91        )
 92    # ### end Alembic commands ###
 93    users_table = table(
 94        "users",
 95        column("id", sa.Integer),
 96        column("status", sa.String),
 97        column("expire_date", sa.DateTime),
 98        column("expire_strategy", sa.Enum(name="userexpirestrategy")),
 99    )
100
101    connection = op.get_bind()
102    results = connection.execute(
103        sa.select(
104            users_table.c.id, users_table.c.status, users_table.c.expire_date
105        )
106    )
107
108    for user in results:
109        status = user[1]
110        expire_date = user[2]
111
112        if status == "on_hold":
113            expire_strategy = "START_ON_FIRST_USE"
114        elif expire_date:
115            expire_strategy = "FIXED_DATE"
116        else:
117            expire_strategy = "NEVER"
118        connection.execute(
119            users_table.update()
120            .where(users_table.c.id == user[0])
121            .values(expire_strategy=expire_strategy)
122        )
123
124    op.drop_column("users", "status")
125
126
127def downgrade() -> None:
128    # ### commands auto generated by Alembic - please adjust! ###
129    op.add_column(
130        "users",
131        sa.Column(
132            "status",
133            postgresql.ENUM(
134                "active", "limited", "expired", "on_hold", name="userstatus"
135            ),
136            autoincrement=False,
137            nullable=False,
138            server_default="active",
139        ),
140    )
141    op.alter_column(
142        "users",
143        "activation_deadline",
144        new_column_name="on_hold_timeout",
145        existing_type=sa.DateTime,
146    )
147    op.alter_column(
148        "users",
149        "usage_duration",
150        new_column_name="on_hold_expire_duration",
151        existing_type=sa.BigInteger,
152    )
153    op.alter_column(
154        "users",
155        "expire_date",
156        new_column_name="expire",
157        existing_type=sa.DateTime,
158    )
159    op.drop_column("users", "expire_strategy")
160    op.drop_column("users", "activated")
161    # ### end Alembic commands ###