Add files via upload

This commit is contained in:
Egor
2026-01-15 17:31:15 +03:00
committed by GitHub
parent a2a09c8914
commit 13770a01c6
2 changed files with 90 additions and 0 deletions

View File

@@ -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"

View File

@@ -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: