From 2c2bdf02905b2e9f05e90bfa2ed7f2fc00ab2019 Mon Sep 17 00:00:00 2001 From: Pine Date: Sun, 6 Sep 2026 18:20:32 +0800 Subject: [PATCH] =?UTF-8?q?fix:=200064=E8=BF=81=E7=A7=BB=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E5=B9=82=E7=AD=89=E6=93=8D=E4=BD=9C(=E5=88=97/=E8=A1=A8?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E6=80=A7=E6=A3=80=E6=9F=A5),=E9=81=BF?= =?UTF-8?q?=E5=85=8DDuplicate=20column=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../versions/0064_compute_discount_balance.py | 95 +++++++++++++------ 1 file changed, 67 insertions(+), 28 deletions(-) diff --git a/alembic/versions/0064_compute_discount_balance.py b/alembic/versions/0064_compute_discount_balance.py index c14c159..8b80e0e 100644 --- a/alembic/versions/0064_compute_discount_balance.py +++ b/alembic/versions/0064_compute_discount_balance.py @@ -7,6 +7,7 @@ Create Date: 2026-09-06 """ from alembic import op import sqlalchemy as sa +from sqlalchemy import inspect revision = "0064" @@ -15,24 +16,48 @@ branch_labels = None depends_on = None +def _column_exists(table_name: str, column_name: str) -> bool: + bind = op.get_bind() + insp = inspect(bind) + if not insp.has_table(table_name): + return False + return column_name in [c["name"] for c in insp.get_columns(table_name)] + + +def _table_exists(table_name: str) -> bool: + bind = op.get_bind() + insp = inspect(bind) + return insp.has_table(table_name) + + +def _add_column_if_not_exists(table_name: str, column): + if not _column_exists(table_name, column.name): + op.add_column(table_name, column) + + +def _create_table_if_not_exists(table_name: str, *columns, **kwargs): + if not _table_exists(table_name): + op.create_table(table_name, *columns, **kwargs) + + def upgrade(): # ── 扩展 park_tenants 表 ── - op.add_column("park_tenants", sa.Column("default_company_discount", sa.Integer(), nullable=False, server_default="0")) - op.add_column("park_tenants", sa.Column("default_user_discount", sa.Integer(), nullable=False, server_default="0")) + _add_column_if_not_exists("park_tenants", sa.Column("default_company_discount", sa.Integer(), nullable=False, server_default="0")) + _add_column_if_not_exists("park_tenants", sa.Column("default_user_discount", sa.Integer(), nullable=False, server_default="0")) # ── 扩展 park_companies 表 ── - op.add_column("park_companies", sa.Column("compute_balance", sa.Integer(), nullable=False, server_default="0")) - op.add_column("park_companies", sa.Column("compute_balance_used", sa.Integer(), nullable=False, server_default="0")) + _add_column_if_not_exists("park_companies", sa.Column("compute_balance", sa.Integer(), nullable=False, server_default="0")) + _add_column_if_not_exists("park_companies", sa.Column("compute_balance_used", sa.Integer(), nullable=False, server_default="0")) # ── 扩展 company_members 表 ── - op.add_column("company_members", sa.Column("role", sa.String(length=32), nullable=False, server_default="staff")) - op.add_column("company_members", sa.Column("compute_balance", sa.Integer(), nullable=False, server_default="0")) - op.add_column("company_members", sa.Column("compute_balance_used", sa.Integer(), nullable=False, server_default="0")) - op.add_column("company_members", sa.Column("left_at", sa.String(length=32), nullable=False, server_default="")) - op.add_column("company_members", sa.Column("left_reason", sa.Text(), nullable=False, server_default="")) + _add_column_if_not_exists("company_members", sa.Column("role", sa.String(length=32), nullable=False, server_default="staff")) + _add_column_if_not_exists("company_members", sa.Column("compute_balance", sa.Integer(), nullable=False, server_default="0")) + _add_column_if_not_exists("company_members", sa.Column("compute_balance_used", sa.Integer(), nullable=False, server_default="0")) + _add_column_if_not_exists("company_members", sa.Column("left_at", sa.String(length=32), nullable=False, server_default="")) + _add_column_if_not_exists("company_members", sa.Column("left_reason", sa.Text(), nullable=False, server_default="")) # ── 新建 tenant_discounts 表 ── - op.create_table( + _create_table_if_not_exists( "tenant_discounts", sa.Column("id", sa.String(length=64), primary_key=True), sa.Column("tenant_id", sa.String(length=64), unique=True, index=True), @@ -45,7 +70,7 @@ def upgrade(): ) # ── 新建 tenant_user_discounts 表 ── - op.create_table( + _create_table_if_not_exists( "tenant_user_discounts", sa.Column("id", sa.String(length=64), primary_key=True), sa.Column("tenant_id", sa.String(length=64), index=True), @@ -58,7 +83,7 @@ def upgrade(): ) # ── 新建 compute_recharges 表 ── - op.create_table( + _create_table_if_not_exists( "compute_recharges", sa.Column("id", sa.String(length=64), primary_key=True), sa.Column("company_id", sa.String(length=64), index=True, server_default=""), @@ -74,7 +99,7 @@ def upgrade(): ) # ── 新建 compute_balance_allocations 表 ── - op.create_table( + _create_table_if_not_exists( "compute_balance_allocations", sa.Column("id", sa.String(length=64), primary_key=True), sa.Column("company_id", sa.String(length=64), index=True), @@ -87,7 +112,7 @@ def upgrade(): ) # ── 新建 compute_usage_records 表 ── - op.create_table( + _create_table_if_not_exists( "compute_usage_records", sa.Column("id", sa.String(length=64), primary_key=True), sa.Column("user_id", sa.String(length=64), index=True), @@ -104,20 +129,34 @@ def upgrade(): def downgrade(): - op.drop_table("compute_usage_records") - op.drop_table("compute_balance_allocations") - op.drop_table("compute_recharges") - op.drop_table("tenant_user_discounts") - op.drop_table("tenant_discounts") + if _table_exists("compute_usage_records"): + op.drop_table("compute_usage_records") + if _table_exists("compute_balance_allocations"): + op.drop_table("compute_balance_allocations") + if _table_exists("compute_recharges"): + op.drop_table("compute_recharges") + if _table_exists("tenant_user_discounts"): + op.drop_table("tenant_user_discounts") + if _table_exists("tenant_discounts"): + op.drop_table("tenant_discounts") - op.drop_column("company_members", "left_reason") - op.drop_column("company_members", "left_at") - op.drop_column("company_members", "compute_balance_used") - op.drop_column("company_members", "compute_balance") - op.drop_column("company_members", "role") + if _column_exists("company_members", "left_reason"): + op.drop_column("company_members", "left_reason") + if _column_exists("company_members", "left_at"): + op.drop_column("company_members", "left_at") + if _column_exists("company_members", "compute_balance_used"): + op.drop_column("company_members", "compute_balance_used") + if _column_exists("company_members", "compute_balance"): + op.drop_column("company_members", "compute_balance") + if _column_exists("company_members", "role"): + op.drop_column("company_members", "role") - op.drop_column("park_companies", "compute_balance_used") - op.drop_column("park_companies", "compute_balance") + if _column_exists("park_companies", "compute_balance_used"): + op.drop_column("park_companies", "compute_balance_used") + if _column_exists("park_companies", "compute_balance"): + op.drop_column("park_companies", "compute_balance") - op.drop_column("park_tenants", "default_user_discount") - op.drop_column("park_tenants", "default_company_discount") + if _column_exists("park_tenants", "default_user_discount"): + op.drop_column("park_tenants", "default_user_discount") + if _column_exists("park_tenants", "default_company_discount"): + op.drop_column("park_tenants", "default_company_discount")