2026-03-18 17:18:23 +08:00
|
|
|
|
"""Plan service — 套餐定义与查询。"""
|
|
|
|
|
|
|
2026-04-08 15:37:09 +08:00
|
|
|
|
from app.features.plan.catalog import (
|
|
|
|
|
|
AVAILABLE_PLANS,
|
|
|
|
|
|
ENABLE_TEST_PLAN,
|
|
|
|
|
|
TEST_PLAN,
|
|
|
|
|
|
get_plan_by_type,
|
|
|
|
|
|
get_plans_for_api,
|
|
|
|
|
|
)
|
2026-05-22 13:44:50 +08:00
|
|
|
|
from app.features.plan.schemas import (
|
|
|
|
|
|
CurrentPlanResponse,
|
|
|
|
|
|
PlanResponse,
|
|
|
|
|
|
PlanUsageResponse,
|
|
|
|
|
|
)
|
2026-03-18 17:18:23 +08:00
|
|
|
|
from app.features.quota.service import QuotaService
|
|
|
|
|
|
from app.features.user.models import User
|
|
|
|
|
|
|
2026-04-08 15:37:09 +08:00
|
|
|
|
__all__ = [
|
|
|
|
|
|
"AVAILABLE_PLANS",
|
|
|
|
|
|
"ENABLE_TEST_PLAN",
|
|
|
|
|
|
"TEST_PLAN",
|
|
|
|
|
|
"PlanService",
|
|
|
|
|
|
"get_plan_by_type",
|
|
|
|
|
|
"get_plans_for_api",
|
2026-03-18 17:18:23 +08:00
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PlanService:
|
|
|
|
|
|
def __init__(self, quota_service: QuotaService):
|
|
|
|
|
|
self._quota = quota_service
|
|
|
|
|
|
|
|
|
|
|
|
def get_plans_for_api(self) -> list[PlanResponse]:
|
|
|
|
|
|
"""对外套餐列表(供 payment 等 feature 通过注入使用,不直接 import plan.service)。"""
|
|
|
|
|
|
return get_plans_for_api()
|
|
|
|
|
|
|
|
|
|
|
|
async def get_current_plan_response(self, user: User) -> CurrentPlanResponse:
|
|
|
|
|
|
plan = get_plan_by_type(user.subscription_type)
|
|
|
|
|
|
segment_count, chapter_count = await self._quota.get_usage(user.id)
|
2026-05-22 13:44:50 +08:00
|
|
|
|
usage = PlanUsageResponse(
|
|
|
|
|
|
conversations=segment_count,
|
|
|
|
|
|
chapters=chapter_count,
|
|
|
|
|
|
max_conversations=plan.max_conversations,
|
|
|
|
|
|
max_chapters=plan.max_chapters,
|
|
|
|
|
|
)
|
2026-03-18 17:18:23 +08:00
|
|
|
|
expires_at = None
|
|
|
|
|
|
if user.subscription_expires_at:
|
|
|
|
|
|
expires_at = user.subscription_expires_at.isoformat()
|
|
|
|
|
|
return CurrentPlanResponse(
|
|
|
|
|
|
plan_id=plan.id,
|
|
|
|
|
|
plan_name=plan.display_name,
|
|
|
|
|
|
subscription_type=user.subscription_type,
|
|
|
|
|
|
expires_at=expires_at,
|
|
|
|
|
|
features=plan.features,
|
|
|
|
|
|
usage=usage,
|
|
|
|
|
|
)
|