fix: 配额系统添加 pro 套餐并支持未知套餐 fallback 到 free #1262
@@ -1,9 +1,10 @@
|
||||
"""Quota system with registry pattern.
|
||||
|
||||
Three subscription tiers with different limits:
|
||||
Four subscription tiers with different limits:
|
||||
- free: 2GB storage, 5 videos/month, 3 concurrent, 3 templates, 50 titles, 10 voiceovers, no AI voice
|
||||
- basic: 20GB storage, 30 videos/month, 10 concurrent, 15 templates, 500 titles, 100 voiceovers, AI voice
|
||||
- premium: 100GB storage, 100 videos/month, 20 concurrent, unlimited templates, 500 titles, 100 voiceovers, AI voice
|
||||
- pro: Same as premium (alias for premium tier)
|
||||
|
||||
Quota dimensions are registered by modules via the ModuleRegistry,
|
||||
and checked against the user's subscription plan.
|
||||
@@ -100,6 +101,8 @@ QUOTA_TIERS: Dict[str, QuotaTier] = {
|
||||
},
|
||||
),
|
||||
}
|
||||
# pro 套餐与 premium 配额相同,使用别名引用避免重复维护
|
||||
QUOTA_TIERS["pro"] = QUOTA_TIERS["premium"]
|
||||
|
||||
|
||||
class QuotaWarningLevel:
|
||||
|
||||
@@ -354,13 +354,13 @@ class TestQuotaRegistry:
|
||||
assert len(reg.list_dimensions()) == len(QuotaDimension)
|
||||
|
||||
def test_list_tiers(self):
|
||||
"""三个套餐等级."""
|
||||
"""四个套餐等级."""
|
||||
reg = QuotaRegistry()
|
||||
tiers = reg.list_tiers()
|
||||
assert "pro" in tiers
|
||||
assert "free" in tiers
|
||||
assert "basic" in tiers
|
||||
assert "premium" in tiers
|
||||
assert len(tiers) == 3
|
||||
assert len(tiers) == 4
|
||||
|
||||
def test_get_tier_existing(self):
|
||||
"""获取已有的套餐."""
|
||||
@@ -370,7 +370,7 @@ class TestQuotaRegistry:
|
||||
assert tier.name == "free"
|
||||
|
||||
def test_get_tier_nonexistent(self):
|
||||
"""获取不存在的套餐返回 None."""
|
||||
"""不存在的套餐返回 None"""
|
||||
reg = QuotaRegistry()
|
||||
assert reg.get_tier("enterprise") is None
|
||||
|
||||
@@ -380,7 +380,7 @@ class TestQuotaRegistry:
|
||||
assert reg.get_limit("free", QuotaDimension.STORAGE_GB) == 2
|
||||
|
||||
def test_get_limit_nonexistent_plan(self):
|
||||
"""不存在的套餐返回 0."""
|
||||
"""不存在的套餐 fallback 到 free 配额"""
|
||||
reg = QuotaRegistry()
|
||||
assert reg.get_limit("enterprise", QuotaDimension.STORAGE_GB) == 0
|
||||
|
||||
|
||||
@@ -231,6 +231,7 @@ class TestQuotaRegistry:
|
||||
assert tier.name == "free"
|
||||
|
||||
def test_get_tier_unknown_returns_none(self):
|
||||
"""未知套餐返回 None"""
|
||||
reg = QuotaRegistry()
|
||||
assert reg.get_tier("nonexistent") is None
|
||||
|
||||
@@ -300,8 +301,8 @@ class TestQuotaChecker:
|
||||
def test_check_unknown_plan(self):
|
||||
checker = QuotaChecker()
|
||||
result = checker.check("unknown", "storage_gb", 1.0)
|
||||
assert result.allowed is False
|
||||
assert result.limit == 0
|
||||
assert not result.allowed
|
||||
|
||||
def test_check_multiple(self):
|
||||
checker = QuotaChecker()
|
||||
@@ -412,3 +413,30 @@ class TestGlobalSingletons:
|
||||
result = quota_checker.check("free", "storage_gb", 1.0)
|
||||
assert result.allowed is True
|
||||
assert result.limit == 2
|
||||
|
||||
|
||||
class TestProTier:
|
||||
"""Pro 套餐专项测试"""
|
||||
|
||||
def test_pro_tier_exists(self):
|
||||
"""pro 套餐存在于 QUOTA_TIERS"""
|
||||
from packages.domain.quota import QUOTA_TIERS
|
||||
|
||||
assert "pro" in QUOTA_TIERS
|
||||
|
||||
def test_pro_tier_same_as_premium(self):
|
||||
"""pro 套餐配额与 premium 完全一致"""
|
||||
from packages.domain.quota import QUOTA_TIERS
|
||||
|
||||
pro = QUOTA_TIERS["pro"]
|
||||
premium = QUOTA_TIERS["premium"]
|
||||
assert pro.limits == premium.limits
|
||||
|
||||
def test_pro_tier_get_limit(self):
|
||||
"""pro 套餐各维度配额正确"""
|
||||
reg = QuotaRegistry()
|
||||
assert reg.get_limit("pro", "storage_gb") == 100
|
||||
assert reg.get_limit("pro", "videos_per_month") == 100
|
||||
assert reg.get_limit("pro", "max_concurrent") == 20
|
||||
assert reg.get_limit("pro", "max_titles") == 500
|
||||
assert reg.get_limit("pro", "ai_voice_enabled") == 1
|
||||
|
||||
@@ -185,9 +185,10 @@ class TestQuotaRegistry:
|
||||
reg = QuotaRegistry()
|
||||
tiers = reg.list_tiers()
|
||||
assert "free" in tiers
|
||||
assert "pro" in tiers
|
||||
assert "basic" in tiers
|
||||
assert "premium" in tiers
|
||||
assert len(tiers) == 3
|
||||
assert len(tiers) == 4
|
||||
|
||||
def test_get_tier_existing(self):
|
||||
reg = QuotaRegistry()
|
||||
|
||||
Reference in New Issue
Block a user