feat(subscriptions): migrate subscription management to merchant level and seed tiers
Move subscription create/edit from store detail (broken endpoint) to merchant detail page with proper modal UI. Seed 4 subscription tiers (Essential, Professional, Business, Enterprise) in init_production.py. Also includes cross-module dependency declarations, store domain platform_id migration, platform context middleware, CMS route fixes, and migration backups. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
128
alembic/versions_backup/za0k1l2m3n4o5_add_admin_menu_config.py
Normal file
128
alembic/versions_backup/za0k1l2m3n4o5_add_admin_menu_config.py
Normal file
@@ -0,0 +1,128 @@
|
||||
"""Add admin menu configuration table
|
||||
|
||||
Revision ID: za0k1l2m3n4o5
|
||||
Revises: z9j0k1l2m3n4
|
||||
Create Date: 2026-01-25
|
||||
|
||||
Adds configurable admin sidebar menus:
|
||||
- Platform-level config: Controls which menu items platform admins see
|
||||
- User-level config: Controls which menu items super admins see
|
||||
- Opt-out model: All items visible by default
|
||||
- Mandatory items enforced at application level (companies, vendors, users, settings)
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "za0k1l2m3n4o5"
|
||||
down_revision = "z9j0k1l2m3n4"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# Create admin_menu_configs table
|
||||
op.create_table(
|
||||
"admin_menu_configs",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column(
|
||||
"platform_id",
|
||||
sa.Integer(),
|
||||
nullable=True,
|
||||
comment="Platform scope - applies to all platform admins of this platform",
|
||||
),
|
||||
sa.Column(
|
||||
"user_id",
|
||||
sa.Integer(),
|
||||
nullable=True,
|
||||
comment="User scope - applies to this specific super admin",
|
||||
),
|
||||
sa.Column(
|
||||
"menu_item_id",
|
||||
sa.String(50),
|
||||
nullable=False,
|
||||
comment="Menu item identifier from registry (e.g., 'products', 'inventory')",
|
||||
),
|
||||
sa.Column(
|
||||
"is_visible",
|
||||
sa.Boolean(),
|
||||
nullable=False,
|
||||
server_default="true",
|
||||
comment="Whether this menu item is visible (False = hidden)",
|
||||
),
|
||||
sa.Column(
|
||||
"created_at",
|
||||
sa.DateTime(timezone=True),
|
||||
nullable=False,
|
||||
server_default=sa.func.now(),
|
||||
),
|
||||
sa.Column(
|
||||
"updated_at",
|
||||
sa.DateTime(timezone=True),
|
||||
nullable=False,
|
||||
server_default=sa.func.now(),
|
||||
onupdate=sa.func.now(),
|
||||
),
|
||||
# Foreign keys
|
||||
sa.ForeignKeyConstraint(
|
||||
["platform_id"],
|
||||
["platforms.id"],
|
||||
ondelete="CASCADE",
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
["user_id"],
|
||||
["users.id"],
|
||||
ondelete="CASCADE",
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
# Unique constraints
|
||||
sa.UniqueConstraint("platform_id", "menu_item_id", name="uq_platform_menu_config"),
|
||||
sa.UniqueConstraint("user_id", "menu_item_id", name="uq_user_menu_config"),
|
||||
# Check constraint: exactly one scope must be set
|
||||
sa.CheckConstraint(
|
||||
"(platform_id IS NOT NULL AND user_id IS NULL) OR "
|
||||
"(platform_id IS NULL AND user_id IS NOT NULL)",
|
||||
name="ck_admin_menu_config_scope",
|
||||
),
|
||||
)
|
||||
|
||||
# Create indexes for performance
|
||||
op.create_index(
|
||||
"idx_admin_menu_configs_platform_id",
|
||||
"admin_menu_configs",
|
||||
["platform_id"],
|
||||
)
|
||||
op.create_index(
|
||||
"idx_admin_menu_configs_user_id",
|
||||
"admin_menu_configs",
|
||||
["user_id"],
|
||||
)
|
||||
op.create_index(
|
||||
"idx_admin_menu_configs_menu_item_id",
|
||||
"admin_menu_configs",
|
||||
["menu_item_id"],
|
||||
)
|
||||
op.create_index(
|
||||
"idx_admin_menu_config_platform_visible",
|
||||
"admin_menu_configs",
|
||||
["platform_id", "is_visible"],
|
||||
)
|
||||
op.create_index(
|
||||
"idx_admin_menu_config_user_visible",
|
||||
"admin_menu_configs",
|
||||
["user_id", "is_visible"],
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# Drop indexes
|
||||
op.drop_index("idx_admin_menu_config_user_visible", table_name="admin_menu_configs")
|
||||
op.drop_index("idx_admin_menu_config_platform_visible", table_name="admin_menu_configs")
|
||||
op.drop_index("idx_admin_menu_configs_menu_item_id", table_name="admin_menu_configs")
|
||||
op.drop_index("idx_admin_menu_configs_user_id", table_name="admin_menu_configs")
|
||||
op.drop_index("idx_admin_menu_configs_platform_id", table_name="admin_menu_configs")
|
||||
|
||||
# Drop table
|
||||
op.drop_table("admin_menu_configs")
|
||||
Reference in New Issue
Block a user