mirror of
https://github.com/BEDOLAGA-DEV/remnawave-bedolaga-telegram-bot.git
synced 2026-02-21 03:40:55 +00:00
209 lines
7.3 KiB
Python
209 lines
7.3 KiB
Python
"""Schemas for tariff management in cabinet."""
|
||
|
||
from datetime import datetime
|
||
from typing import List, Optional, Dict
|
||
from pydantic import BaseModel, Field
|
||
|
||
|
||
class PeriodPrice(BaseModel):
|
||
"""Price for a specific period."""
|
||
days: int = Field(..., ge=1, description="Period in days")
|
||
price_kopeks: int = Field(..., ge=0, description="Price in kopeks")
|
||
price_rubles: Optional[float] = None
|
||
|
||
def __init__(self, **data):
|
||
super().__init__(**data)
|
||
if self.price_rubles is None:
|
||
self.price_rubles = self.price_kopeks / 100
|
||
|
||
|
||
class ServerTrafficLimit(BaseModel):
|
||
"""Traffic limit for a specific server."""
|
||
traffic_limit_gb: int = Field(0, ge=0, description="0 = use default tariff limit")
|
||
|
||
|
||
class ServerInfo(BaseModel):
|
||
"""Server info for tariff."""
|
||
id: int
|
||
squad_uuid: str
|
||
display_name: str
|
||
country_code: Optional[str] = None
|
||
is_selected: bool = False
|
||
traffic_limit_gb: Optional[int] = None # Индивидуальный лимит для сервера
|
||
|
||
|
||
class PromoGroupInfo(BaseModel):
|
||
"""Promo group info for tariff."""
|
||
id: int
|
||
name: str
|
||
is_selected: bool = False
|
||
|
||
|
||
class TariffListItem(BaseModel):
|
||
"""Tariff item for list view."""
|
||
id: int
|
||
name: str
|
||
description: Optional[str] = None
|
||
is_active: bool
|
||
is_trial_available: bool
|
||
is_daily: bool = False
|
||
daily_price_kopeks: int = 0
|
||
allow_traffic_topup: bool = True
|
||
traffic_limit_gb: int
|
||
device_limit: int
|
||
tier_level: int
|
||
display_order: int
|
||
servers_count: int
|
||
subscriptions_count: int
|
||
created_at: datetime
|
||
|
||
class Config:
|
||
from_attributes = True
|
||
|
||
|
||
class TariffListResponse(BaseModel):
|
||
"""Response with list of tariffs."""
|
||
tariffs: List[TariffListItem]
|
||
total: int
|
||
|
||
|
||
class TariffDetailResponse(BaseModel):
|
||
"""Detailed tariff response."""
|
||
id: int
|
||
name: str
|
||
description: Optional[str] = None
|
||
is_active: bool
|
||
is_trial_available: bool
|
||
allow_traffic_topup: bool = True
|
||
traffic_topup_enabled: bool = False
|
||
traffic_topup_packages: Dict[str, int] = Field(default_factory=dict)
|
||
max_topup_traffic_gb: int = 0
|
||
traffic_limit_gb: int
|
||
device_limit: int
|
||
device_price_kopeks: Optional[int] = None
|
||
max_device_limit: Optional[int] = None
|
||
tier_level: int
|
||
display_order: int
|
||
period_prices: List[PeriodPrice]
|
||
allowed_squads: List[str] # UUIDs
|
||
server_traffic_limits: Dict[str, ServerTrafficLimit] = Field(default_factory=dict) # {uuid: {traffic_limit_gb}}
|
||
servers: List[ServerInfo]
|
||
promo_groups: List[PromoGroupInfo]
|
||
subscriptions_count: int
|
||
# Произвольное количество дней
|
||
custom_days_enabled: bool = False
|
||
price_per_day_kopeks: int = 0
|
||
min_days: int = 1
|
||
max_days: int = 365
|
||
# Произвольный трафик при покупке
|
||
custom_traffic_enabled: bool = False
|
||
traffic_price_per_gb_kopeks: int = 0
|
||
min_traffic_gb: int = 1
|
||
max_traffic_gb: int = 1000
|
||
# Дневной тариф
|
||
is_daily: bool = False
|
||
daily_price_kopeks: int = 0
|
||
# Режим сброса трафика
|
||
traffic_reset_mode: Optional[str] = None # DAY, WEEK, MONTH, NO_RESET, None = глобальная настройка
|
||
created_at: datetime
|
||
updated_at: Optional[datetime] = None
|
||
|
||
class Config:
|
||
from_attributes = True
|
||
|
||
|
||
class TariffCreateRequest(BaseModel):
|
||
"""Request to create a tariff."""
|
||
name: str = Field(..., min_length=1, max_length=255)
|
||
description: Optional[str] = None
|
||
is_active: bool = True
|
||
allow_traffic_topup: bool = True
|
||
traffic_topup_enabled: bool = False
|
||
traffic_topup_packages: Dict[str, int] = Field(default_factory=dict)
|
||
max_topup_traffic_gb: int = Field(0, ge=0)
|
||
traffic_limit_gb: int = Field(0, ge=0, description="0 = unlimited")
|
||
device_limit: int = Field(1, ge=1)
|
||
device_price_kopeks: Optional[int] = Field(None, ge=0)
|
||
max_device_limit: Optional[int] = Field(None, ge=1)
|
||
tier_level: int = Field(1, ge=1, le=10)
|
||
period_prices: List[PeriodPrice] = Field(default_factory=list)
|
||
allowed_squads: List[str] = Field(default_factory=list, description="Server UUIDs")
|
||
server_traffic_limits: Dict[str, ServerTrafficLimit] = Field(default_factory=dict, description="Per-server traffic limits")
|
||
promo_group_ids: List[int] = Field(default_factory=list)
|
||
# Произвольное количество дней
|
||
custom_days_enabled: bool = False
|
||
price_per_day_kopeks: int = Field(0, ge=0)
|
||
min_days: int = Field(1, ge=1)
|
||
max_days: int = Field(365, ge=1)
|
||
# Произвольный трафик при покупке
|
||
custom_traffic_enabled: bool = False
|
||
traffic_price_per_gb_kopeks: int = Field(0, ge=0)
|
||
min_traffic_gb: int = Field(1, ge=1)
|
||
max_traffic_gb: int = Field(1000, ge=1)
|
||
# Дневной тариф
|
||
is_daily: bool = False
|
||
daily_price_kopeks: int = Field(0, ge=0)
|
||
# Режим сброса трафика
|
||
traffic_reset_mode: Optional[str] = None # DAY, WEEK, MONTH, NO_RESET, None = глобальная настройка
|
||
|
||
|
||
class TariffUpdateRequest(BaseModel):
|
||
"""Request to update a tariff."""
|
||
name: Optional[str] = Field(None, min_length=1, max_length=255)
|
||
description: Optional[str] = None
|
||
is_active: Optional[bool] = None
|
||
allow_traffic_topup: Optional[bool] = None
|
||
traffic_topup_enabled: Optional[bool] = None
|
||
traffic_topup_packages: Optional[Dict[str, int]] = None
|
||
max_topup_traffic_gb: Optional[int] = Field(None, ge=0)
|
||
traffic_limit_gb: Optional[int] = Field(None, ge=0)
|
||
device_limit: Optional[int] = Field(None, ge=1)
|
||
device_price_kopeks: Optional[int] = Field(None, ge=0)
|
||
max_device_limit: Optional[int] = Field(None, ge=1)
|
||
tier_level: Optional[int] = Field(None, ge=1, le=10)
|
||
display_order: Optional[int] = Field(None, ge=0)
|
||
period_prices: Optional[List[PeriodPrice]] = None
|
||
allowed_squads: Optional[List[str]] = None
|
||
server_traffic_limits: Optional[Dict[str, ServerTrafficLimit]] = None
|
||
promo_group_ids: Optional[List[int]] = None
|
||
# Произвольное количество дней
|
||
custom_days_enabled: Optional[bool] = None
|
||
price_per_day_kopeks: Optional[int] = Field(None, ge=0)
|
||
min_days: Optional[int] = Field(None, ge=1)
|
||
max_days: Optional[int] = Field(None, ge=1)
|
||
# Произвольный трафик при покупке
|
||
custom_traffic_enabled: Optional[bool] = None
|
||
traffic_price_per_gb_kopeks: Optional[int] = Field(None, ge=0)
|
||
min_traffic_gb: Optional[int] = Field(None, ge=1)
|
||
max_traffic_gb: Optional[int] = Field(None, ge=1)
|
||
# Дневной тариф
|
||
is_daily: Optional[bool] = None
|
||
daily_price_kopeks: Optional[int] = Field(None, ge=0)
|
||
# Режим сброса трафика
|
||
traffic_reset_mode: Optional[str] = None # DAY, WEEK, MONTH, NO_RESET, None = глобальная настройка
|
||
|
||
|
||
class TariffToggleResponse(BaseModel):
|
||
"""Response after toggling tariff."""
|
||
id: int
|
||
is_active: bool
|
||
message: str
|
||
|
||
|
||
class TariffTrialResponse(BaseModel):
|
||
"""Response after setting trial tariff."""
|
||
id: int
|
||
is_trial_available: bool
|
||
message: str
|
||
|
||
|
||
class TariffStatsResponse(BaseModel):
|
||
"""Tariff statistics."""
|
||
id: int
|
||
name: str
|
||
subscriptions_count: int
|
||
active_subscriptions: int
|
||
trial_subscriptions: int
|
||
revenue_kopeks: int
|
||
revenue_rubles: float
|