"""Tariff service for VoIdea.""" from decimal import Decimal from typing import Any, Optional from uuid import UUID from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.models.tariff import TariffPlan, UserSubscription class TariffService: def __init__(self, db: AsyncSession): self.db = db # ── Plans ── async def list_plans(self, active_only: bool = True) -> list[TariffPlan]: query = select(TariffPlan) if active_only: query = query.where(TariffPlan.is_active.is_(True)) query = query.order_by(TariffPlan.sort_order) result = await self.db.execute(query) return list(result.scalars().all()) async def get_plan_by_id(self, plan_id: UUID) -> Optional[TariffPlan]: return await self.db.get(TariffPlan, plan_id) async def get_plan_by_code(self, code: str) -> Optional[TariffPlan]: result = await self.db.execute( select(TariffPlan).where(TariffPlan.code == code) ) return result.scalar_one_or_none() async def create_plan( self, name: str, code: str, description: Optional[str] = None, price_monthly: Decimal = Decimal("0"), price_yearly: Optional[Decimal] = None, features: Optional[dict[str, Any]] = None, is_active: bool = True, sort_order: int = 0, ) -> TariffPlan: plan = TariffPlan( name=name, code=code, description=description, price_monthly=price_monthly, price_yearly=price_yearly, features=features, is_active=is_active, sort_order=sort_order, ) self.db.add(plan) await self.db.commit() await self.db.refresh(plan) return plan async def update_plan( self, plan_id: UUID, updates: dict[str, Any] ) -> Optional[TariffPlan]: plan = await self.get_plan_by_id(plan_id) if not plan: return None for key, value in updates.items(): if hasattr(plan, key) and key not in ("id", "code", "created_at"): setattr(plan, key, value) await self.db.commit() await self.db.refresh(plan) return plan async def delete_plan(self, plan_id: UUID) -> bool: plan = await self.get_plan_by_id(plan_id) if not plan: return False await self.db.delete(plan) await self.db.commit() return True # ── Subscriptions ── async def get_user_subscription(self, user_id: UUID) -> Optional[UserSubscription]: result = await self.db.execute( select(UserSubscription).where(UserSubscription.user_id == user_id) ) return result.scalar_one_or_none() async def assign_plan(self, user_id: UUID, plan_code: str) -> Optional[UserSubscription]: plan = await self.get_plan_by_code(plan_code) if not plan: return None sub = await self.get_user_subscription(user_id) if sub: sub.plan_id = plan.id sub.status = "active" else: sub = UserSubscription( user_id=user_id, plan_id=plan.id, status="active", ) self.db.add(sub) await self.db.commit() await self.db.refresh(sub) return sub