mirror of
https://github.com/BEDOLAGA-DEV/remnawave-bedolaga-telegram-bot.git
synced 2026-01-20 03:40:26 +00:00
Add files via upload
This commit is contained in:
@@ -1080,6 +1080,7 @@ class Subscription(Base):
|
||||
tariff = relationship("Tariff", back_populates="subscriptions")
|
||||
discount_offers = relationship("DiscountOffer", back_populates="subscription")
|
||||
temporary_accesses = relationship("SubscriptionTemporaryAccess", back_populates="subscription")
|
||||
traffic_purchases = relationship("TrafficPurchase", back_populates="subscription", cascade="all, delete-orphan")
|
||||
|
||||
@property
|
||||
def is_active(self) -> bool:
|
||||
@@ -1238,6 +1239,26 @@ class Subscription(Base):
|
||||
return True
|
||||
|
||||
|
||||
class TrafficPurchase(Base):
|
||||
"""Докупка трафика с индивидуальной датой истечения."""
|
||||
__tablename__ = "traffic_purchases"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
subscription_id = Column(Integer, ForeignKey("subscriptions.id", ondelete="CASCADE"), nullable=False, index=True)
|
||||
|
||||
traffic_gb = Column(Integer, nullable=False) # Количество ГБ в покупке
|
||||
expires_at = Column(DateTime, nullable=False, index=True) # Дата истечения (покупка + 30 дней)
|
||||
|
||||
created_at = Column(DateTime, default=func.now())
|
||||
|
||||
subscription = relationship("Subscription", back_populates="traffic_purchases")
|
||||
|
||||
@property
|
||||
def is_expired(self) -> bool:
|
||||
"""Проверяет, истекла ли докупка."""
|
||||
return datetime.utcnow() >= self.expires_at
|
||||
|
||||
|
||||
class Transaction(Base):
|
||||
__tablename__ = "transactions"
|
||||
|
||||
|
||||
@@ -5135,6 +5135,68 @@ async def create_withdrawal_requests_table() -> bool:
|
||||
return False
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# МИГРАЦИЯ ДЛЯ ИНДИВИДУАЛЬНЫХ ДОКУПОК ТРАФИКА
|
||||
# =============================================================================
|
||||
|
||||
async def create_traffic_purchases_table() -> bool:
|
||||
"""Создаёт таблицу для индивидуальных докупок трафика с отдельными датами истечения."""
|
||||
try:
|
||||
if await check_table_exists('traffic_purchases'):
|
||||
logger.info("ℹ️ Таблица traffic_purchases уже существует")
|
||||
return True
|
||||
|
||||
async with engine.begin() as conn:
|
||||
db_type = await get_database_type()
|
||||
|
||||
if db_type == 'sqlite':
|
||||
create_sql = """
|
||||
CREATE TABLE traffic_purchases (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
subscription_id INTEGER NOT NULL,
|
||||
traffic_gb INTEGER NOT NULL,
|
||||
expires_at DATETIME NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (subscription_id) REFERENCES subscriptions(id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX idx_traffic_purchases_subscription_id ON traffic_purchases(subscription_id);
|
||||
CREATE INDEX idx_traffic_purchases_expires_at ON traffic_purchases(expires_at);
|
||||
"""
|
||||
elif db_type == 'postgresql':
|
||||
create_sql = """
|
||||
CREATE TABLE traffic_purchases (
|
||||
id SERIAL PRIMARY KEY,
|
||||
subscription_id INTEGER NOT NULL REFERENCES subscriptions(id) ON DELETE CASCADE,
|
||||
traffic_gb INTEGER NOT NULL,
|
||||
expires_at TIMESTAMP NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE INDEX idx_traffic_purchases_subscription_id ON traffic_purchases(subscription_id);
|
||||
CREATE INDEX idx_traffic_purchases_expires_at ON traffic_purchases(expires_at);
|
||||
"""
|
||||
else: # mysql
|
||||
create_sql = """
|
||||
CREATE TABLE traffic_purchases (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
subscription_id INT NOT NULL,
|
||||
traffic_gb INT NOT NULL,
|
||||
expires_at DATETIME NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (subscription_id) REFERENCES subscriptions(id) ON DELETE CASCADE,
|
||||
INDEX idx_traffic_purchases_subscription_id (subscription_id),
|
||||
INDEX idx_traffic_purchases_expires_at (expires_at)
|
||||
);
|
||||
"""
|
||||
|
||||
await conn.execute(text(create_sql))
|
||||
logger.info("✅ Таблица traffic_purchases создана")
|
||||
|
||||
return True
|
||||
except Exception as error:
|
||||
logger.error(f"❌ Ошибка создания таблицы traffic_purchases: {error}")
|
||||
return False
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# МИГРАЦИИ ДЛЯ РЕЖИМА ТАРИФОВ
|
||||
# =============================================================================
|
||||
@@ -6460,6 +6522,13 @@ async def run_universal_migration():
|
||||
else:
|
||||
logger.warning("⚠️ Проблемы с настройкой доступа серверов к промогруппам")
|
||||
|
||||
logger.info("=== СОЗДАНИЕ ТАБЛИЦЫ ДОКУПОК ТРАФИКА ===")
|
||||
traffic_purchases_ready = await create_traffic_purchases_table()
|
||||
if traffic_purchases_ready:
|
||||
logger.info("✅ Таблица traffic_purchases готова")
|
||||
else:
|
||||
logger.warning("⚠️ Проблемы с таблицей traffic_purchases")
|
||||
|
||||
logger.info("=== СОЗДАНИЕ ТАБЛИЦ ДЛЯ РЕЖИМА ТАРИФОВ ===")
|
||||
tariffs_table_ready = await create_tariffs_table()
|
||||
if tariffs_table_ready:
|
||||
|
||||
Reference in New Issue
Block a user