fix(lint): auto-fix ruff violations and tune lint rules
- Auto-fixed 4,496 lint issues (import sorting, modern syntax, etc.) - Added ignore rules for patterns intentional in this codebase: E402 (late imports), E712 (SQLAlchemy filters), B904 (raise from), SIM108/SIM105/SIM117 (readability preferences) - Added per-file ignores for tests and scripts - Excluded broken scripts/rename_terminology.py (has curly quotes) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,18 +5,20 @@ Revises: e1bfb453fbe9
|
||||
Create Date: 2025-12-25 18:29:34.167773
|
||||
|
||||
"""
|
||||
from collections.abc import Sequence
|
||||
from datetime import datetime
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
# Removed: from sqlalchemy.dialects import sqlite (using sa.JSON for PostgreSQL)
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '2953ed10d22c'
|
||||
down_revision: Union[str, None] = 'e1bfb453fbe9'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
revision: str = "2953ed10d22c"
|
||||
down_revision: str | None = "e1bfb453fbe9"
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
@@ -25,146 +27,146 @@ def upgrade() -> None:
|
||||
# =========================================================================
|
||||
|
||||
# subscription_tiers - Database-driven tier definitions
|
||||
op.create_table('subscription_tiers',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('code', sa.String(length=30), nullable=False),
|
||||
sa.Column('name', sa.String(length=100), nullable=False),
|
||||
sa.Column('description', sa.Text(), nullable=True),
|
||||
sa.Column('price_monthly_cents', sa.Integer(), nullable=False),
|
||||
sa.Column('price_annual_cents', sa.Integer(), nullable=True),
|
||||
sa.Column('orders_per_month', sa.Integer(), nullable=True),
|
||||
sa.Column('products_limit', sa.Integer(), nullable=True),
|
||||
sa.Column('team_members', sa.Integer(), nullable=True),
|
||||
sa.Column('order_history_months', sa.Integer(), nullable=True),
|
||||
sa.Column('features', sa.JSON(), nullable=True),
|
||||
sa.Column('stripe_product_id', sa.String(length=100), nullable=True),
|
||||
sa.Column('stripe_price_monthly_id', sa.String(length=100), nullable=True),
|
||||
sa.Column('stripe_price_annual_id', sa.String(length=100), nullable=True),
|
||||
sa.Column('display_order', sa.Integer(), nullable=True),
|
||||
sa.Column('is_active', sa.Boolean(), nullable=False),
|
||||
sa.Column('is_public', sa.Boolean(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
op.create_table("subscription_tiers",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("code", sa.String(length=30), nullable=False),
|
||||
sa.Column("name", sa.String(length=100), nullable=False),
|
||||
sa.Column("description", sa.Text(), nullable=True),
|
||||
sa.Column("price_monthly_cents", sa.Integer(), nullable=False),
|
||||
sa.Column("price_annual_cents", sa.Integer(), nullable=True),
|
||||
sa.Column("orders_per_month", sa.Integer(), nullable=True),
|
||||
sa.Column("products_limit", sa.Integer(), nullable=True),
|
||||
sa.Column("team_members", sa.Integer(), nullable=True),
|
||||
sa.Column("order_history_months", sa.Integer(), nullable=True),
|
||||
sa.Column("features", sa.JSON(), nullable=True),
|
||||
sa.Column("stripe_product_id", sa.String(length=100), nullable=True),
|
||||
sa.Column("stripe_price_monthly_id", sa.String(length=100), nullable=True),
|
||||
sa.Column("stripe_price_annual_id", sa.String(length=100), nullable=True),
|
||||
sa.Column("display_order", sa.Integer(), nullable=True),
|
||||
sa.Column("is_active", sa.Boolean(), nullable=False),
|
||||
sa.Column("is_public", sa.Boolean(), nullable=False),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("updated_at", sa.DateTime(), nullable=False),
|
||||
sa.PrimaryKeyConstraint("id")
|
||||
)
|
||||
op.create_index(op.f('ix_subscription_tiers_code'), 'subscription_tiers', ['code'], unique=True)
|
||||
op.create_index(op.f('ix_subscription_tiers_id'), 'subscription_tiers', ['id'], unique=False)
|
||||
op.create_index(op.f("ix_subscription_tiers_code"), "subscription_tiers", ["code"], unique=True)
|
||||
op.create_index(op.f("ix_subscription_tiers_id"), "subscription_tiers", ["id"], unique=False)
|
||||
|
||||
# addon_products - Purchasable add-ons (domains, SSL, email)
|
||||
op.create_table('addon_products',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('code', sa.String(length=50), nullable=False),
|
||||
sa.Column('name', sa.String(length=100), nullable=False),
|
||||
sa.Column('description', sa.Text(), nullable=True),
|
||||
sa.Column('category', sa.String(length=50), nullable=False),
|
||||
sa.Column('price_cents', sa.Integer(), nullable=False),
|
||||
sa.Column('billing_period', sa.String(length=20), nullable=False),
|
||||
sa.Column('quantity_unit', sa.String(length=50), nullable=True),
|
||||
sa.Column('quantity_value', sa.Integer(), nullable=True),
|
||||
sa.Column('stripe_product_id', sa.String(length=100), nullable=True),
|
||||
sa.Column('stripe_price_id', sa.String(length=100), nullable=True),
|
||||
sa.Column('display_order', sa.Integer(), nullable=True),
|
||||
sa.Column('is_active', sa.Boolean(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
op.create_table("addon_products",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("code", sa.String(length=50), nullable=False),
|
||||
sa.Column("name", sa.String(length=100), nullable=False),
|
||||
sa.Column("description", sa.Text(), nullable=True),
|
||||
sa.Column("category", sa.String(length=50), nullable=False),
|
||||
sa.Column("price_cents", sa.Integer(), nullable=False),
|
||||
sa.Column("billing_period", sa.String(length=20), nullable=False),
|
||||
sa.Column("quantity_unit", sa.String(length=50), nullable=True),
|
||||
sa.Column("quantity_value", sa.Integer(), nullable=True),
|
||||
sa.Column("stripe_product_id", sa.String(length=100), nullable=True),
|
||||
sa.Column("stripe_price_id", sa.String(length=100), nullable=True),
|
||||
sa.Column("display_order", sa.Integer(), nullable=True),
|
||||
sa.Column("is_active", sa.Boolean(), nullable=False),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("updated_at", sa.DateTime(), nullable=False),
|
||||
sa.PrimaryKeyConstraint("id")
|
||||
)
|
||||
op.create_index(op.f('ix_addon_products_category'), 'addon_products', ['category'], unique=False)
|
||||
op.create_index(op.f('ix_addon_products_code'), 'addon_products', ['code'], unique=True)
|
||||
op.create_index(op.f('ix_addon_products_id'), 'addon_products', ['id'], unique=False)
|
||||
op.create_index(op.f("ix_addon_products_category"), "addon_products", ["category"], unique=False)
|
||||
op.create_index(op.f("ix_addon_products_code"), "addon_products", ["code"], unique=True)
|
||||
op.create_index(op.f("ix_addon_products_id"), "addon_products", ["id"], unique=False)
|
||||
|
||||
# billing_history - Invoice and payment history
|
||||
op.create_table('billing_history',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('vendor_id', sa.Integer(), nullable=False),
|
||||
sa.Column('stripe_invoice_id', sa.String(length=100), nullable=True),
|
||||
sa.Column('stripe_payment_intent_id', sa.String(length=100), nullable=True),
|
||||
sa.Column('invoice_number', sa.String(length=50), nullable=True),
|
||||
sa.Column('invoice_date', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('due_date', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('subtotal_cents', sa.Integer(), nullable=False),
|
||||
sa.Column('tax_cents', sa.Integer(), nullable=False),
|
||||
sa.Column('total_cents', sa.Integer(), nullable=False),
|
||||
sa.Column('amount_paid_cents', sa.Integer(), nullable=False),
|
||||
sa.Column('currency', sa.String(length=3), nullable=False),
|
||||
sa.Column('status', sa.String(length=20), nullable=False),
|
||||
sa.Column('invoice_pdf_url', sa.String(length=500), nullable=True),
|
||||
sa.Column('hosted_invoice_url', sa.String(length=500), nullable=True),
|
||||
sa.Column('description', sa.Text(), nullable=True),
|
||||
sa.Column('line_items', sa.JSON(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['vendor_id'], ['vendors.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
op.create_table("billing_history",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("vendor_id", sa.Integer(), nullable=False),
|
||||
sa.Column("stripe_invoice_id", sa.String(length=100), nullable=True),
|
||||
sa.Column("stripe_payment_intent_id", sa.String(length=100), nullable=True),
|
||||
sa.Column("invoice_number", sa.String(length=50), nullable=True),
|
||||
sa.Column("invoice_date", sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column("due_date", sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column("subtotal_cents", sa.Integer(), nullable=False),
|
||||
sa.Column("tax_cents", sa.Integer(), nullable=False),
|
||||
sa.Column("total_cents", sa.Integer(), nullable=False),
|
||||
sa.Column("amount_paid_cents", sa.Integer(), nullable=False),
|
||||
sa.Column("currency", sa.String(length=3), nullable=False),
|
||||
sa.Column("status", sa.String(length=20), nullable=False),
|
||||
sa.Column("invoice_pdf_url", sa.String(length=500), nullable=True),
|
||||
sa.Column("hosted_invoice_url", sa.String(length=500), nullable=True),
|
||||
sa.Column("description", sa.Text(), nullable=True),
|
||||
sa.Column("line_items", sa.JSON(), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("updated_at", sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(["vendor_id"], ["vendors.id"], ),
|
||||
sa.PrimaryKeyConstraint("id")
|
||||
)
|
||||
op.create_index('idx_billing_status', 'billing_history', ['vendor_id', 'status'], unique=False)
|
||||
op.create_index('idx_billing_vendor_date', 'billing_history', ['vendor_id', 'invoice_date'], unique=False)
|
||||
op.create_index(op.f('ix_billing_history_id'), 'billing_history', ['id'], unique=False)
|
||||
op.create_index(op.f('ix_billing_history_status'), 'billing_history', ['status'], unique=False)
|
||||
op.create_index(op.f('ix_billing_history_stripe_invoice_id'), 'billing_history', ['stripe_invoice_id'], unique=True)
|
||||
op.create_index(op.f('ix_billing_history_vendor_id'), 'billing_history', ['vendor_id'], unique=False)
|
||||
op.create_index("idx_billing_status", "billing_history", ["vendor_id", "status"], unique=False)
|
||||
op.create_index("idx_billing_vendor_date", "billing_history", ["vendor_id", "invoice_date"], unique=False)
|
||||
op.create_index(op.f("ix_billing_history_id"), "billing_history", ["id"], unique=False)
|
||||
op.create_index(op.f("ix_billing_history_status"), "billing_history", ["status"], unique=False)
|
||||
op.create_index(op.f("ix_billing_history_stripe_invoice_id"), "billing_history", ["stripe_invoice_id"], unique=True)
|
||||
op.create_index(op.f("ix_billing_history_vendor_id"), "billing_history", ["vendor_id"], unique=False)
|
||||
|
||||
# vendor_addons - Add-ons purchased by vendor
|
||||
op.create_table('vendor_addons',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('vendor_id', sa.Integer(), nullable=False),
|
||||
sa.Column('addon_product_id', sa.Integer(), nullable=False),
|
||||
sa.Column('status', sa.String(length=20), nullable=False),
|
||||
sa.Column('domain_name', sa.String(length=255), nullable=True),
|
||||
sa.Column('quantity', sa.Integer(), nullable=False),
|
||||
sa.Column('stripe_subscription_item_id', sa.String(length=100), nullable=True),
|
||||
sa.Column('period_start', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('period_end', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('cancelled_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['addon_product_id'], ['addon_products.id'], ),
|
||||
sa.ForeignKeyConstraint(['vendor_id'], ['vendors.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
op.create_table("vendor_addons",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("vendor_id", sa.Integer(), nullable=False),
|
||||
sa.Column("addon_product_id", sa.Integer(), nullable=False),
|
||||
sa.Column("status", sa.String(length=20), nullable=False),
|
||||
sa.Column("domain_name", sa.String(length=255), nullable=True),
|
||||
sa.Column("quantity", sa.Integer(), nullable=False),
|
||||
sa.Column("stripe_subscription_item_id", sa.String(length=100), nullable=True),
|
||||
sa.Column("period_start", sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column("period_end", sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column("cancelled_at", sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("updated_at", sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(["addon_product_id"], ["addon_products.id"], ),
|
||||
sa.ForeignKeyConstraint(["vendor_id"], ["vendors.id"], ),
|
||||
sa.PrimaryKeyConstraint("id")
|
||||
)
|
||||
op.create_index('idx_vendor_addon_product', 'vendor_addons', ['vendor_id', 'addon_product_id'], unique=False)
|
||||
op.create_index('idx_vendor_addon_status', 'vendor_addons', ['vendor_id', 'status'], unique=False)
|
||||
op.create_index(op.f('ix_vendor_addons_addon_product_id'), 'vendor_addons', ['addon_product_id'], unique=False)
|
||||
op.create_index(op.f('ix_vendor_addons_domain_name'), 'vendor_addons', ['domain_name'], unique=False)
|
||||
op.create_index(op.f('ix_vendor_addons_id'), 'vendor_addons', ['id'], unique=False)
|
||||
op.create_index(op.f('ix_vendor_addons_status'), 'vendor_addons', ['status'], unique=False)
|
||||
op.create_index(op.f('ix_vendor_addons_vendor_id'), 'vendor_addons', ['vendor_id'], unique=False)
|
||||
op.create_index("idx_vendor_addon_product", "vendor_addons", ["vendor_id", "addon_product_id"], unique=False)
|
||||
op.create_index("idx_vendor_addon_status", "vendor_addons", ["vendor_id", "status"], unique=False)
|
||||
op.create_index(op.f("ix_vendor_addons_addon_product_id"), "vendor_addons", ["addon_product_id"], unique=False)
|
||||
op.create_index(op.f("ix_vendor_addons_domain_name"), "vendor_addons", ["domain_name"], unique=False)
|
||||
op.create_index(op.f("ix_vendor_addons_id"), "vendor_addons", ["id"], unique=False)
|
||||
op.create_index(op.f("ix_vendor_addons_status"), "vendor_addons", ["status"], unique=False)
|
||||
op.create_index(op.f("ix_vendor_addons_vendor_id"), "vendor_addons", ["vendor_id"], unique=False)
|
||||
|
||||
# stripe_webhook_events - Webhook idempotency tracking
|
||||
op.create_table('stripe_webhook_events',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('event_id', sa.String(length=100), nullable=False),
|
||||
sa.Column('event_type', sa.String(length=100), nullable=False),
|
||||
sa.Column('status', sa.String(length=20), nullable=False),
|
||||
sa.Column('processed_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('error_message', sa.Text(), nullable=True),
|
||||
sa.Column('payload_encrypted', sa.Text(), nullable=True),
|
||||
sa.Column('vendor_id', sa.Integer(), nullable=True),
|
||||
sa.Column('subscription_id', sa.Integer(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['subscription_id'], ['vendor_subscriptions.id'], ),
|
||||
sa.ForeignKeyConstraint(['vendor_id'], ['vendors.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
op.create_table("stripe_webhook_events",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("event_id", sa.String(length=100), nullable=False),
|
||||
sa.Column("event_type", sa.String(length=100), nullable=False),
|
||||
sa.Column("status", sa.String(length=20), nullable=False),
|
||||
sa.Column("processed_at", sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column("error_message", sa.Text(), nullable=True),
|
||||
sa.Column("payload_encrypted", sa.Text(), nullable=True),
|
||||
sa.Column("vendor_id", sa.Integer(), nullable=True),
|
||||
sa.Column("subscription_id", sa.Integer(), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("updated_at", sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(["subscription_id"], ["vendor_subscriptions.id"], ),
|
||||
sa.ForeignKeyConstraint(["vendor_id"], ["vendors.id"], ),
|
||||
sa.PrimaryKeyConstraint("id")
|
||||
)
|
||||
op.create_index('idx_webhook_event_type_status', 'stripe_webhook_events', ['event_type', 'status'], unique=False)
|
||||
op.create_index(op.f('ix_stripe_webhook_events_event_id'), 'stripe_webhook_events', ['event_id'], unique=True)
|
||||
op.create_index(op.f('ix_stripe_webhook_events_event_type'), 'stripe_webhook_events', ['event_type'], unique=False)
|
||||
op.create_index(op.f('ix_stripe_webhook_events_id'), 'stripe_webhook_events', ['id'], unique=False)
|
||||
op.create_index(op.f('ix_stripe_webhook_events_status'), 'stripe_webhook_events', ['status'], unique=False)
|
||||
op.create_index(op.f('ix_stripe_webhook_events_subscription_id'), 'stripe_webhook_events', ['subscription_id'], unique=False)
|
||||
op.create_index(op.f('ix_stripe_webhook_events_vendor_id'), 'stripe_webhook_events', ['vendor_id'], unique=False)
|
||||
op.create_index("idx_webhook_event_type_status", "stripe_webhook_events", ["event_type", "status"], unique=False)
|
||||
op.create_index(op.f("ix_stripe_webhook_events_event_id"), "stripe_webhook_events", ["event_id"], unique=True)
|
||||
op.create_index(op.f("ix_stripe_webhook_events_event_type"), "stripe_webhook_events", ["event_type"], unique=False)
|
||||
op.create_index(op.f("ix_stripe_webhook_events_id"), "stripe_webhook_events", ["id"], unique=False)
|
||||
op.create_index(op.f("ix_stripe_webhook_events_status"), "stripe_webhook_events", ["status"], unique=False)
|
||||
op.create_index(op.f("ix_stripe_webhook_events_subscription_id"), "stripe_webhook_events", ["subscription_id"], unique=False)
|
||||
op.create_index(op.f("ix_stripe_webhook_events_vendor_id"), "stripe_webhook_events", ["vendor_id"], unique=False)
|
||||
|
||||
# =========================================================================
|
||||
# Add new columns to vendor_subscriptions
|
||||
# =========================================================================
|
||||
op.add_column('vendor_subscriptions', sa.Column('stripe_price_id', sa.String(length=100), nullable=True))
|
||||
op.add_column('vendor_subscriptions', sa.Column('stripe_payment_method_id', sa.String(length=100), nullable=True))
|
||||
op.add_column('vendor_subscriptions', sa.Column('proration_behavior', sa.String(length=50), nullable=True))
|
||||
op.add_column('vendor_subscriptions', sa.Column('scheduled_tier_change', sa.String(length=30), nullable=True))
|
||||
op.add_column('vendor_subscriptions', sa.Column('scheduled_change_at', sa.DateTime(timezone=True), nullable=True))
|
||||
op.add_column('vendor_subscriptions', sa.Column('payment_retry_count', sa.Integer(), server_default='0', nullable=False))
|
||||
op.add_column('vendor_subscriptions', sa.Column('last_payment_error', sa.Text(), nullable=True))
|
||||
op.add_column("vendor_subscriptions", sa.Column("stripe_price_id", sa.String(length=100), nullable=True))
|
||||
op.add_column("vendor_subscriptions", sa.Column("stripe_payment_method_id", sa.String(length=100), nullable=True))
|
||||
op.add_column("vendor_subscriptions", sa.Column("proration_behavior", sa.String(length=50), nullable=True))
|
||||
op.add_column("vendor_subscriptions", sa.Column("scheduled_tier_change", sa.String(length=30), nullable=True))
|
||||
op.add_column("vendor_subscriptions", sa.Column("scheduled_change_at", sa.DateTime(timezone=True), nullable=True))
|
||||
op.add_column("vendor_subscriptions", sa.Column("payment_retry_count", sa.Integer(), server_default="0", nullable=False))
|
||||
op.add_column("vendor_subscriptions", sa.Column("last_payment_error", sa.Text(), nullable=True))
|
||||
|
||||
# =========================================================================
|
||||
# Seed subscription tiers
|
||||
@@ -172,106 +174,106 @@ def upgrade() -> None:
|
||||
now = datetime.utcnow()
|
||||
|
||||
subscription_tiers = sa.table(
|
||||
'subscription_tiers',
|
||||
sa.column('code', sa.String),
|
||||
sa.column('name', sa.String),
|
||||
sa.column('description', sa.Text),
|
||||
sa.column('price_monthly_cents', sa.Integer),
|
||||
sa.column('price_annual_cents', sa.Integer),
|
||||
sa.column('orders_per_month', sa.Integer),
|
||||
sa.column('products_limit', sa.Integer),
|
||||
sa.column('team_members', sa.Integer),
|
||||
sa.column('order_history_months', sa.Integer),
|
||||
sa.column('features', sa.JSON),
|
||||
sa.column('display_order', sa.Integer),
|
||||
sa.column('is_active', sa.Boolean),
|
||||
sa.column('is_public', sa.Boolean),
|
||||
sa.column('created_at', sa.DateTime),
|
||||
sa.column('updated_at', sa.DateTime),
|
||||
"subscription_tiers",
|
||||
sa.column("code", sa.String),
|
||||
sa.column("name", sa.String),
|
||||
sa.column("description", sa.Text),
|
||||
sa.column("price_monthly_cents", sa.Integer),
|
||||
sa.column("price_annual_cents", sa.Integer),
|
||||
sa.column("orders_per_month", sa.Integer),
|
||||
sa.column("products_limit", sa.Integer),
|
||||
sa.column("team_members", sa.Integer),
|
||||
sa.column("order_history_months", sa.Integer),
|
||||
sa.column("features", sa.JSON),
|
||||
sa.column("display_order", sa.Integer),
|
||||
sa.column("is_active", sa.Boolean),
|
||||
sa.column("is_public", sa.Boolean),
|
||||
sa.column("created_at", sa.DateTime),
|
||||
sa.column("updated_at", sa.DateTime),
|
||||
)
|
||||
|
||||
op.bulk_insert(subscription_tiers, [
|
||||
{
|
||||
'code': 'essential',
|
||||
'name': 'Essential',
|
||||
'description': 'Perfect for solo vendors getting started with Letzshop',
|
||||
'price_monthly_cents': 4900,
|
||||
'price_annual_cents': 49000,
|
||||
'orders_per_month': 100,
|
||||
'products_limit': 200,
|
||||
'team_members': 1,
|
||||
'order_history_months': 6,
|
||||
'features': ['letzshop_sync', 'inventory_basic', 'invoice_lu', 'customer_view'],
|
||||
'display_order': 1,
|
||||
'is_active': True,
|
||||
'is_public': True,
|
||||
'created_at': now,
|
||||
'updated_at': now,
|
||||
"code": "essential",
|
||||
"name": "Essential",
|
||||
"description": "Perfect for solo vendors getting started with Letzshop",
|
||||
"price_monthly_cents": 4900,
|
||||
"price_annual_cents": 49000,
|
||||
"orders_per_month": 100,
|
||||
"products_limit": 200,
|
||||
"team_members": 1,
|
||||
"order_history_months": 6,
|
||||
"features": ["letzshop_sync", "inventory_basic", "invoice_lu", "customer_view"],
|
||||
"display_order": 1,
|
||||
"is_active": True,
|
||||
"is_public": True,
|
||||
"created_at": now,
|
||||
"updated_at": now,
|
||||
},
|
||||
{
|
||||
'code': 'professional',
|
||||
'name': 'Professional',
|
||||
'description': 'For active multi-channel vendors shipping EU-wide',
|
||||
'price_monthly_cents': 9900,
|
||||
'price_annual_cents': 99000,
|
||||
'orders_per_month': 500,
|
||||
'products_limit': None,
|
||||
'team_members': 3,
|
||||
'order_history_months': 24,
|
||||
'features': [
|
||||
'letzshop_sync', 'inventory_locations', 'inventory_purchase_orders',
|
||||
'invoice_lu', 'invoice_eu_vat', 'customer_view', 'customer_export'
|
||||
"code": "professional",
|
||||
"name": "Professional",
|
||||
"description": "For active multi-channel vendors shipping EU-wide",
|
||||
"price_monthly_cents": 9900,
|
||||
"price_annual_cents": 99000,
|
||||
"orders_per_month": 500,
|
||||
"products_limit": None,
|
||||
"team_members": 3,
|
||||
"order_history_months": 24,
|
||||
"features": [
|
||||
"letzshop_sync", "inventory_locations", "inventory_purchase_orders",
|
||||
"invoice_lu", "invoice_eu_vat", "customer_view", "customer_export"
|
||||
],
|
||||
'display_order': 2,
|
||||
'is_active': True,
|
||||
'is_public': True,
|
||||
'created_at': now,
|
||||
'updated_at': now,
|
||||
"display_order": 2,
|
||||
"is_active": True,
|
||||
"is_public": True,
|
||||
"created_at": now,
|
||||
"updated_at": now,
|
||||
},
|
||||
{
|
||||
'code': 'business',
|
||||
'name': 'Business',
|
||||
'description': 'For high-volume vendors with teams and data-driven operations',
|
||||
'price_monthly_cents': 19900,
|
||||
'price_annual_cents': 199000,
|
||||
'orders_per_month': 2000,
|
||||
'products_limit': None,
|
||||
'team_members': 10,
|
||||
'order_history_months': None,
|
||||
'features': [
|
||||
'letzshop_sync', 'inventory_locations', 'inventory_purchase_orders',
|
||||
'invoice_lu', 'invoice_eu_vat', 'invoice_bulk', 'customer_view',
|
||||
'customer_export', 'analytics_dashboard', 'accounting_export',
|
||||
'api_access', 'automation_rules', 'team_roles'
|
||||
"code": "business",
|
||||
"name": "Business",
|
||||
"description": "For high-volume vendors with teams and data-driven operations",
|
||||
"price_monthly_cents": 19900,
|
||||
"price_annual_cents": 199000,
|
||||
"orders_per_month": 2000,
|
||||
"products_limit": None,
|
||||
"team_members": 10,
|
||||
"order_history_months": None,
|
||||
"features": [
|
||||
"letzshop_sync", "inventory_locations", "inventory_purchase_orders",
|
||||
"invoice_lu", "invoice_eu_vat", "invoice_bulk", "customer_view",
|
||||
"customer_export", "analytics_dashboard", "accounting_export",
|
||||
"api_access", "automation_rules", "team_roles"
|
||||
],
|
||||
'display_order': 3,
|
||||
'is_active': True,
|
||||
'is_public': True,
|
||||
'created_at': now,
|
||||
'updated_at': now,
|
||||
"display_order": 3,
|
||||
"is_active": True,
|
||||
"is_public": True,
|
||||
"created_at": now,
|
||||
"updated_at": now,
|
||||
},
|
||||
{
|
||||
'code': 'enterprise',
|
||||
'name': 'Enterprise',
|
||||
'description': 'Custom solutions for large operations and agencies',
|
||||
'price_monthly_cents': 39900,
|
||||
'price_annual_cents': None,
|
||||
'orders_per_month': None,
|
||||
'products_limit': None,
|
||||
'team_members': None,
|
||||
'order_history_months': None,
|
||||
'features': [
|
||||
'letzshop_sync', 'inventory_locations', 'inventory_purchase_orders',
|
||||
'invoice_lu', 'invoice_eu_vat', 'invoice_bulk', 'customer_view',
|
||||
'customer_export', 'analytics_dashboard', 'accounting_export',
|
||||
'api_access', 'automation_rules', 'team_roles', 'white_label',
|
||||
'multi_vendor', 'custom_integrations', 'sla_guarantee', 'dedicated_support'
|
||||
"code": "enterprise",
|
||||
"name": "Enterprise",
|
||||
"description": "Custom solutions for large operations and agencies",
|
||||
"price_monthly_cents": 39900,
|
||||
"price_annual_cents": None,
|
||||
"orders_per_month": None,
|
||||
"products_limit": None,
|
||||
"team_members": None,
|
||||
"order_history_months": None,
|
||||
"features": [
|
||||
"letzshop_sync", "inventory_locations", "inventory_purchase_orders",
|
||||
"invoice_lu", "invoice_eu_vat", "invoice_bulk", "customer_view",
|
||||
"customer_export", "analytics_dashboard", "accounting_export",
|
||||
"api_access", "automation_rules", "team_roles", "white_label",
|
||||
"multi_vendor", "custom_integrations", "sla_guarantee", "dedicated_support"
|
||||
],
|
||||
'display_order': 4,
|
||||
'is_active': True,
|
||||
'is_public': False,
|
||||
'created_at': now,
|
||||
'updated_at': now,
|
||||
"display_order": 4,
|
||||
"is_active": True,
|
||||
"is_public": False,
|
||||
"created_at": now,
|
||||
"updated_at": now,
|
||||
},
|
||||
])
|
||||
|
||||
@@ -279,141 +281,141 @@ def upgrade() -> None:
|
||||
# Seed add-on products
|
||||
# =========================================================================
|
||||
addon_products = sa.table(
|
||||
'addon_products',
|
||||
sa.column('code', sa.String),
|
||||
sa.column('name', sa.String),
|
||||
sa.column('description', sa.Text),
|
||||
sa.column('category', sa.String),
|
||||
sa.column('price_cents', sa.Integer),
|
||||
sa.column('billing_period', sa.String),
|
||||
sa.column('quantity_unit', sa.String),
|
||||
sa.column('quantity_value', sa.Integer),
|
||||
sa.column('display_order', sa.Integer),
|
||||
sa.column('is_active', sa.Boolean),
|
||||
sa.column('created_at', sa.DateTime),
|
||||
sa.column('updated_at', sa.DateTime),
|
||||
"addon_products",
|
||||
sa.column("code", sa.String),
|
||||
sa.column("name", sa.String),
|
||||
sa.column("description", sa.Text),
|
||||
sa.column("category", sa.String),
|
||||
sa.column("price_cents", sa.Integer),
|
||||
sa.column("billing_period", sa.String),
|
||||
sa.column("quantity_unit", sa.String),
|
||||
sa.column("quantity_value", sa.Integer),
|
||||
sa.column("display_order", sa.Integer),
|
||||
sa.column("is_active", sa.Boolean),
|
||||
sa.column("created_at", sa.DateTime),
|
||||
sa.column("updated_at", sa.DateTime),
|
||||
)
|
||||
|
||||
op.bulk_insert(addon_products, [
|
||||
{
|
||||
'code': 'domain',
|
||||
'name': 'Custom Domain',
|
||||
'description': 'Connect your own domain with SSL certificate included',
|
||||
'category': 'domain',
|
||||
'price_cents': 1500,
|
||||
'billing_period': 'annual',
|
||||
'quantity_unit': None,
|
||||
'quantity_value': None,
|
||||
'display_order': 1,
|
||||
'is_active': True,
|
||||
'created_at': now,
|
||||
'updated_at': now,
|
||||
"code": "domain",
|
||||
"name": "Custom Domain",
|
||||
"description": "Connect your own domain with SSL certificate included",
|
||||
"category": "domain",
|
||||
"price_cents": 1500,
|
||||
"billing_period": "annual",
|
||||
"quantity_unit": None,
|
||||
"quantity_value": None,
|
||||
"display_order": 1,
|
||||
"is_active": True,
|
||||
"created_at": now,
|
||||
"updated_at": now,
|
||||
},
|
||||
{
|
||||
'code': 'email_5',
|
||||
'name': '5 Email Addresses',
|
||||
'description': 'Professional email addresses on your domain',
|
||||
'category': 'email',
|
||||
'price_cents': 500,
|
||||
'billing_period': 'monthly',
|
||||
'quantity_unit': 'emails',
|
||||
'quantity_value': 5,
|
||||
'display_order': 2,
|
||||
'is_active': True,
|
||||
'created_at': now,
|
||||
'updated_at': now,
|
||||
"code": "email_5",
|
||||
"name": "5 Email Addresses",
|
||||
"description": "Professional email addresses on your domain",
|
||||
"category": "email",
|
||||
"price_cents": 500,
|
||||
"billing_period": "monthly",
|
||||
"quantity_unit": "emails",
|
||||
"quantity_value": 5,
|
||||
"display_order": 2,
|
||||
"is_active": True,
|
||||
"created_at": now,
|
||||
"updated_at": now,
|
||||
},
|
||||
{
|
||||
'code': 'email_10',
|
||||
'name': '10 Email Addresses',
|
||||
'description': 'Professional email addresses on your domain',
|
||||
'category': 'email',
|
||||
'price_cents': 900,
|
||||
'billing_period': 'monthly',
|
||||
'quantity_unit': 'emails',
|
||||
'quantity_value': 10,
|
||||
'display_order': 3,
|
||||
'is_active': True,
|
||||
'created_at': now,
|
||||
'updated_at': now,
|
||||
"code": "email_10",
|
||||
"name": "10 Email Addresses",
|
||||
"description": "Professional email addresses on your domain",
|
||||
"category": "email",
|
||||
"price_cents": 900,
|
||||
"billing_period": "monthly",
|
||||
"quantity_unit": "emails",
|
||||
"quantity_value": 10,
|
||||
"display_order": 3,
|
||||
"is_active": True,
|
||||
"created_at": now,
|
||||
"updated_at": now,
|
||||
},
|
||||
{
|
||||
'code': 'email_25',
|
||||
'name': '25 Email Addresses',
|
||||
'description': 'Professional email addresses on your domain',
|
||||
'category': 'email',
|
||||
'price_cents': 1900,
|
||||
'billing_period': 'monthly',
|
||||
'quantity_unit': 'emails',
|
||||
'quantity_value': 25,
|
||||
'display_order': 4,
|
||||
'is_active': True,
|
||||
'created_at': now,
|
||||
'updated_at': now,
|
||||
"code": "email_25",
|
||||
"name": "25 Email Addresses",
|
||||
"description": "Professional email addresses on your domain",
|
||||
"category": "email",
|
||||
"price_cents": 1900,
|
||||
"billing_period": "monthly",
|
||||
"quantity_unit": "emails",
|
||||
"quantity_value": 25,
|
||||
"display_order": 4,
|
||||
"is_active": True,
|
||||
"created_at": now,
|
||||
"updated_at": now,
|
||||
},
|
||||
{
|
||||
'code': 'storage_10gb',
|
||||
'name': 'Additional Storage (10GB)',
|
||||
'description': 'Extra storage for product images and files',
|
||||
'category': 'storage',
|
||||
'price_cents': 500,
|
||||
'billing_period': 'monthly',
|
||||
'quantity_unit': 'GB',
|
||||
'quantity_value': 10,
|
||||
'display_order': 5,
|
||||
'is_active': True,
|
||||
'created_at': now,
|
||||
'updated_at': now,
|
||||
"code": "storage_10gb",
|
||||
"name": "Additional Storage (10GB)",
|
||||
"description": "Extra storage for product images and files",
|
||||
"category": "storage",
|
||||
"price_cents": 500,
|
||||
"billing_period": "monthly",
|
||||
"quantity_unit": "GB",
|
||||
"quantity_value": 10,
|
||||
"display_order": 5,
|
||||
"is_active": True,
|
||||
"created_at": now,
|
||||
"updated_at": now,
|
||||
},
|
||||
])
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# Remove new columns from vendor_subscriptions
|
||||
op.drop_column('vendor_subscriptions', 'last_payment_error')
|
||||
op.drop_column('vendor_subscriptions', 'payment_retry_count')
|
||||
op.drop_column('vendor_subscriptions', 'scheduled_change_at')
|
||||
op.drop_column('vendor_subscriptions', 'scheduled_tier_change')
|
||||
op.drop_column('vendor_subscriptions', 'proration_behavior')
|
||||
op.drop_column('vendor_subscriptions', 'stripe_payment_method_id')
|
||||
op.drop_column('vendor_subscriptions', 'stripe_price_id')
|
||||
op.drop_column("vendor_subscriptions", "last_payment_error")
|
||||
op.drop_column("vendor_subscriptions", "payment_retry_count")
|
||||
op.drop_column("vendor_subscriptions", "scheduled_change_at")
|
||||
op.drop_column("vendor_subscriptions", "scheduled_tier_change")
|
||||
op.drop_column("vendor_subscriptions", "proration_behavior")
|
||||
op.drop_column("vendor_subscriptions", "stripe_payment_method_id")
|
||||
op.drop_column("vendor_subscriptions", "stripe_price_id")
|
||||
|
||||
# Drop stripe_webhook_events
|
||||
op.drop_index(op.f('ix_stripe_webhook_events_vendor_id'), table_name='stripe_webhook_events')
|
||||
op.drop_index(op.f('ix_stripe_webhook_events_subscription_id'), table_name='stripe_webhook_events')
|
||||
op.drop_index(op.f('ix_stripe_webhook_events_status'), table_name='stripe_webhook_events')
|
||||
op.drop_index(op.f('ix_stripe_webhook_events_id'), table_name='stripe_webhook_events')
|
||||
op.drop_index(op.f('ix_stripe_webhook_events_event_type'), table_name='stripe_webhook_events')
|
||||
op.drop_index(op.f('ix_stripe_webhook_events_event_id'), table_name='stripe_webhook_events')
|
||||
op.drop_index('idx_webhook_event_type_status', table_name='stripe_webhook_events')
|
||||
op.drop_table('stripe_webhook_events')
|
||||
op.drop_index(op.f("ix_stripe_webhook_events_vendor_id"), table_name="stripe_webhook_events")
|
||||
op.drop_index(op.f("ix_stripe_webhook_events_subscription_id"), table_name="stripe_webhook_events")
|
||||
op.drop_index(op.f("ix_stripe_webhook_events_status"), table_name="stripe_webhook_events")
|
||||
op.drop_index(op.f("ix_stripe_webhook_events_id"), table_name="stripe_webhook_events")
|
||||
op.drop_index(op.f("ix_stripe_webhook_events_event_type"), table_name="stripe_webhook_events")
|
||||
op.drop_index(op.f("ix_stripe_webhook_events_event_id"), table_name="stripe_webhook_events")
|
||||
op.drop_index("idx_webhook_event_type_status", table_name="stripe_webhook_events")
|
||||
op.drop_table("stripe_webhook_events")
|
||||
|
||||
# Drop vendor_addons
|
||||
op.drop_index(op.f('ix_vendor_addons_vendor_id'), table_name='vendor_addons')
|
||||
op.drop_index(op.f('ix_vendor_addons_status'), table_name='vendor_addons')
|
||||
op.drop_index(op.f('ix_vendor_addons_id'), table_name='vendor_addons')
|
||||
op.drop_index(op.f('ix_vendor_addons_domain_name'), table_name='vendor_addons')
|
||||
op.drop_index(op.f('ix_vendor_addons_addon_product_id'), table_name='vendor_addons')
|
||||
op.drop_index('idx_vendor_addon_status', table_name='vendor_addons')
|
||||
op.drop_index('idx_vendor_addon_product', table_name='vendor_addons')
|
||||
op.drop_table('vendor_addons')
|
||||
op.drop_index(op.f("ix_vendor_addons_vendor_id"), table_name="vendor_addons")
|
||||
op.drop_index(op.f("ix_vendor_addons_status"), table_name="vendor_addons")
|
||||
op.drop_index(op.f("ix_vendor_addons_id"), table_name="vendor_addons")
|
||||
op.drop_index(op.f("ix_vendor_addons_domain_name"), table_name="vendor_addons")
|
||||
op.drop_index(op.f("ix_vendor_addons_addon_product_id"), table_name="vendor_addons")
|
||||
op.drop_index("idx_vendor_addon_status", table_name="vendor_addons")
|
||||
op.drop_index("idx_vendor_addon_product", table_name="vendor_addons")
|
||||
op.drop_table("vendor_addons")
|
||||
|
||||
# Drop billing_history
|
||||
op.drop_index(op.f('ix_billing_history_vendor_id'), table_name='billing_history')
|
||||
op.drop_index(op.f('ix_billing_history_stripe_invoice_id'), table_name='billing_history')
|
||||
op.drop_index(op.f('ix_billing_history_status'), table_name='billing_history')
|
||||
op.drop_index(op.f('ix_billing_history_id'), table_name='billing_history')
|
||||
op.drop_index('idx_billing_vendor_date', table_name='billing_history')
|
||||
op.drop_index('idx_billing_status', table_name='billing_history')
|
||||
op.drop_table('billing_history')
|
||||
op.drop_index(op.f("ix_billing_history_vendor_id"), table_name="billing_history")
|
||||
op.drop_index(op.f("ix_billing_history_stripe_invoice_id"), table_name="billing_history")
|
||||
op.drop_index(op.f("ix_billing_history_status"), table_name="billing_history")
|
||||
op.drop_index(op.f("ix_billing_history_id"), table_name="billing_history")
|
||||
op.drop_index("idx_billing_vendor_date", table_name="billing_history")
|
||||
op.drop_index("idx_billing_status", table_name="billing_history")
|
||||
op.drop_table("billing_history")
|
||||
|
||||
# Drop addon_products
|
||||
op.drop_index(op.f('ix_addon_products_id'), table_name='addon_products')
|
||||
op.drop_index(op.f('ix_addon_products_code'), table_name='addon_products')
|
||||
op.drop_index(op.f('ix_addon_products_category'), table_name='addon_products')
|
||||
op.drop_table('addon_products')
|
||||
op.drop_index(op.f("ix_addon_products_id"), table_name="addon_products")
|
||||
op.drop_index(op.f("ix_addon_products_code"), table_name="addon_products")
|
||||
op.drop_index(op.f("ix_addon_products_category"), table_name="addon_products")
|
||||
op.drop_table("addon_products")
|
||||
|
||||
# Drop subscription_tiers
|
||||
op.drop_index(op.f('ix_subscription_tiers_id'), table_name='subscription_tiers')
|
||||
op.drop_index(op.f('ix_subscription_tiers_code'), table_name='subscription_tiers')
|
||||
op.drop_table('subscription_tiers')
|
||||
op.drop_index(op.f("ix_subscription_tiers_id"), table_name="subscription_tiers")
|
||||
op.drop_index(op.f("ix_subscription_tiers_code"), table_name="subscription_tiers")
|
||||
op.drop_table("subscription_tiers")
|
||||
|
||||
Reference in New Issue
Block a user