feat: implement tiered subscription plans with usage-based pricing and dynamic plan management
Add multi-tier subscription system (Starter, Professional, Enterprise) with per-tier storage and bandwidth pricing, replace static free-tier limits with nullable usage-based fields in SubscriptionPlan model, introduce subscribe/unsubscribe API endpoints with plan validation, update invoice generator to calculate costs based on user's active plan tier, and refactor pricing page to load plans dynamically from backend API instead of hardcoded HTML.
This commit is contained in:
@@ -59,7 +59,7 @@ async def pricing_config():
|
||||
configs.append(
|
||||
await PricingConfig.create(
|
||||
config_key="storage_per_gb_month",
|
||||
config_value=Decimal("0.0045"),
|
||||
config_value=Decimal("0.005"),
|
||||
description="Storage cost per GB per month",
|
||||
unit="per_gb_month",
|
||||
)
|
||||
@@ -67,27 +67,11 @@ async def pricing_config():
|
||||
configs.append(
|
||||
await PricingConfig.create(
|
||||
config_key="bandwidth_egress_per_gb",
|
||||
config_value=Decimal("0.009"),
|
||||
config_value=Decimal("0.008"),
|
||||
description="Bandwidth egress cost per GB",
|
||||
unit="per_gb",
|
||||
)
|
||||
)
|
||||
configs.append(
|
||||
await PricingConfig.create(
|
||||
config_key="free_tier_storage_gb",
|
||||
config_value=Decimal("15"),
|
||||
description="Free tier storage in GB",
|
||||
unit="gb",
|
||||
)
|
||||
)
|
||||
configs.append(
|
||||
await PricingConfig.create(
|
||||
config_key="free_tier_bandwidth_gb",
|
||||
config_value=Decimal("15"),
|
||||
description="Free tier bandwidth in GB per month",
|
||||
unit="gb",
|
||||
)
|
||||
)
|
||||
yield configs
|
||||
for config in configs:
|
||||
await config.delete()
|
||||
|
||||
@@ -31,7 +31,7 @@ async def pricing_config():
|
||||
configs.append(
|
||||
await PricingConfig.create(
|
||||
config_key="storage_per_gb_month",
|
||||
config_value=Decimal("0.0045"),
|
||||
config_value=Decimal("0.005"),
|
||||
description="Storage cost per GB per month",
|
||||
unit="per_gb_month",
|
||||
)
|
||||
@@ -39,27 +39,11 @@ async def pricing_config():
|
||||
configs.append(
|
||||
await PricingConfig.create(
|
||||
config_key="bandwidth_egress_per_gb",
|
||||
config_value=Decimal("0.009"),
|
||||
config_value=Decimal("0.008"),
|
||||
description="Bandwidth egress cost per GB",
|
||||
unit="per_gb",
|
||||
)
|
||||
)
|
||||
configs.append(
|
||||
await PricingConfig.create(
|
||||
config_key="free_tier_storage_gb",
|
||||
config_value=Decimal("15"),
|
||||
description="Free tier storage in GB",
|
||||
unit="gb",
|
||||
)
|
||||
)
|
||||
configs.append(
|
||||
await PricingConfig.create(
|
||||
config_key="free_tier_bandwidth_gb",
|
||||
config_value=Decimal("15"),
|
||||
description="Free tier bandwidth in GB per month",
|
||||
unit="gb",
|
||||
)
|
||||
)
|
||||
configs.append(
|
||||
await PricingConfig.create(
|
||||
config_key="tax_rate_default",
|
||||
@@ -103,7 +87,7 @@ async def test_generate_monthly_invoice_with_usage(test_user, pricing_config):
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_generate_monthly_invoice_below_free_tier(test_user, pricing_config):
|
||||
async def test_generate_monthly_invoice_with_small_usage(test_user, pricing_config):
|
||||
today = date.today()
|
||||
|
||||
await UsageAggregate.create(
|
||||
@@ -119,8 +103,11 @@ async def test_generate_monthly_invoice_below_free_tier(test_user, pricing_confi
|
||||
test_user, today.year, today.month
|
||||
)
|
||||
|
||||
assert invoice is None
|
||||
# Should always generate invoice now (no free tier)
|
||||
assert invoice is not None
|
||||
assert invoice.total > 0
|
||||
|
||||
await invoice.delete()
|
||||
await UsageAggregate.filter(user=test_user).delete()
|
||||
|
||||
|
||||
|
||||
@@ -143,14 +143,14 @@ async def test_invoice_line_item_creation(test_user):
|
||||
async def test_pricing_config_creation(test_user):
|
||||
config = await PricingConfig.create(
|
||||
config_key="storage_per_gb_month",
|
||||
config_value=Decimal("0.0045"),
|
||||
config_value=Decimal("0.005"),
|
||||
description="Storage cost per GB per month",
|
||||
unit="per_gb_month",
|
||||
updated_by=test_user,
|
||||
)
|
||||
|
||||
assert config.config_key == "storage_per_gb_month"
|
||||
assert config.config_value == Decimal("0.0045")
|
||||
assert config.config_value == Decimal("0.005")
|
||||
await config.delete()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user