diff --git a/app/database/crud/promo_group.py b/app/database/crud/promo_group.py
index 7e5fab72..d63c3107 100644
--- a/app/database/crud/promo_group.py
+++ b/app/database/crud/promo_group.py
@@ -1,7 +1,7 @@
import logging
-from typing import Any, Dict, List, Optional, Tuple
+from typing import Dict, List, Optional, Tuple
-from sqlalchemy import desc, func, select, update
+from sqlalchemy import func, select, update
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
@@ -27,23 +27,6 @@ def _normalize_period_discounts(period_discounts: Optional[Dict[int, int]]) -> D
logger = logging.getLogger(__name__)
-_UNSET = object()
-
-
-def _normalize_auto_assign_amount(amount_kopeks: Optional[int]) -> Optional[int]:
- if amount_kopeks is None:
- return None
-
- try:
- normalized = int(amount_kopeks)
- except (TypeError, ValueError):
- return None
-
- if normalized <= 0:
- return None
-
- return normalized
-
async def get_promo_groups_with_counts(
db: AsyncSession,
@@ -76,10 +59,8 @@ async def create_promo_group(
traffic_discount_percent: int,
device_discount_percent: int,
period_discounts: Optional[Dict[int, int]] = None,
- auto_assign_amount_kopeks: Optional[int] = None,
) -> PromoGroup:
normalized_period_discounts = _normalize_period_discounts(period_discounts)
- normalized_auto_amount = _normalize_auto_assign_amount(auto_assign_amount_kopeks)
promo_group = PromoGroup(
name=name.strip(),
@@ -87,7 +68,6 @@ async def create_promo_group(
traffic_discount_percent=max(0, min(100, traffic_discount_percent)),
device_discount_percent=max(0, min(100, device_discount_percent)),
period_discounts=normalized_period_discounts or None,
- auto_assign_amount_kopeks=normalized_auto_amount,
is_default=False,
)
@@ -116,7 +96,6 @@ async def update_promo_group(
traffic_discount_percent: Optional[int] = None,
device_discount_percent: Optional[int] = None,
period_discounts: Optional[Dict[int, int]] = None,
- auto_assign_amount_kopeks: Any = _UNSET,
) -> PromoGroup:
if name is not None:
group.name = name.strip()
@@ -129,8 +108,6 @@ async def update_promo_group(
if period_discounts is not None:
normalized_period_discounts = _normalize_period_discounts(period_discounts)
group.period_discounts = normalized_period_discounts or None
- if auto_assign_amount_kopeks is not _UNSET:
- group.auto_assign_amount_kopeks = _normalize_auto_assign_amount(auto_assign_amount_kopeks)
await db.commit()
await db.refresh(group)
@@ -193,23 +170,3 @@ async def count_promo_group_members(db: AsyncSession, group_id: int) -> int:
select(func.count(User.id)).where(User.promo_group_id == group_id)
)
return result.scalar_one()
-
-
-async def get_auto_assign_promo_group(
- db: AsyncSession,
- total_amount_kopeks: int,
-) -> Optional[PromoGroup]:
- if total_amount_kopeks <= 0:
- return None
-
- result = await db.execute(
- select(PromoGroup)
- .where(
- PromoGroup.auto_assign_amount_kopeks.is_not(None),
- PromoGroup.auto_assign_amount_kopeks > 0,
- PromoGroup.auto_assign_amount_kopeks <= total_amount_kopeks,
- )
- .order_by(desc(PromoGroup.auto_assign_amount_kopeks), PromoGroup.id)
- )
-
- return result.scalars().first()
diff --git a/app/database/crud/transaction.py b/app/database/crud/transaction.py
index 5102100a..b258f1b2 100644
--- a/app/database/crud/transaction.py
+++ b/app/database/crud/transaction.py
@@ -98,21 +98,6 @@ async def get_user_transactions_count(
return result.scalar()
-async def get_user_total_completed_deposits(db: AsyncSession, user_id: int) -> int:
- result = await db.execute(
- select(func.coalesce(func.sum(Transaction.amount_kopeks), 0))
- .where(
- and_(
- Transaction.user_id == user_id,
- Transaction.type == TransactionType.DEPOSIT.value,
- Transaction.is_completed.is_(True),
- )
- )
- )
-
- return result.scalar_one()
-
-
async def complete_transaction(db: AsyncSession, transaction: Transaction) -> Transaction:
transaction.is_completed = True
diff --git a/app/database/crud/user.py b/app/database/crud/user.py
index 4e228735..582c8695 100644
--- a/app/database/crud/user.py
+++ b/app/database/crud/user.py
@@ -116,7 +116,6 @@ async def create_user(
has_had_paid_subscription=False,
has_made_first_topup=False,
promo_group_id=promo_group_id,
- promo_group_auto_assigned=False,
)
db.add(user)
diff --git a/app/database/models.py b/app/database/models.py
index df882864..9cdeaa86 100644
--- a/app/database/models.py
+++ b/app/database/models.py
@@ -271,7 +271,6 @@ class PromoGroup(Base):
traffic_discount_percent = Column(Integer, nullable=False, default=0)
device_discount_percent = Column(Integer, nullable=False, default=0)
period_discounts = Column(JSON, nullable=True, default=dict)
- auto_assign_amount_kopeks = Column(Integer, nullable=True)
is_default = Column(Boolean, nullable=False, default=False)
created_at = Column(DateTime, default=func.now())
updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
@@ -336,7 +335,7 @@ class PromoGroup(Base):
class User(Base):
__tablename__ = "users"
-
+
id = Column(Integer, primary_key=True, index=True)
telegram_id = Column(BigInteger, unique=True, index=True, nullable=False)
username = Column(String(255), nullable=True)
@@ -366,7 +365,6 @@ class User(Base):
has_made_first_topup: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
promo_group_id = Column(Integer, ForeignKey("promo_groups.id", ondelete="RESTRICT"), nullable=False, index=True)
promo_group = relationship("PromoGroup", back_populates="users")
- promo_group_auto_assigned: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
@property
def balance_rubles(self) -> float:
diff --git a/app/database/universal_migration.py b/app/database/universal_migration.py
index 17179520..ce270f13 100644
--- a/app/database/universal_migration.py
+++ b/app/database/universal_migration.py
@@ -902,81 +902,6 @@ async def ensure_promo_groups_setup():
logger.error(f"Ошибка настройки промо групп: {e}")
return False
-
-async def add_promo_group_auto_assign_column():
- logger.info("=== ДОБАВЛЕНИЕ ПОЛЯ АВТОВЫДАЧИ ДЛЯ ПРОМОГРУПП ===")
-
- try:
- if await check_column_exists("promo_groups", "auto_assign_amount_kopeks"):
- logger.info("Колонка auto_assign_amount_kopeks уже существует в promo_groups")
- return True
-
- db_type = await get_database_type()
-
- if db_type == "sqlite":
- column_definition = "INTEGER"
- elif db_type == "postgresql":
- column_definition = "INTEGER"
- elif db_type == "mysql":
- column_definition = "INT"
- else:
- logger.error(f"Неподдерживаемый тип БД для auto_assign_amount_kopeks: {db_type}")
- return False
-
- async with engine.begin() as conn:
- await conn.execute(
- text(
- f"ALTER TABLE promo_groups ADD COLUMN auto_assign_amount_kopeks {column_definition}"
- )
- )
-
- logger.info("Добавлена колонка promo_groups.auto_assign_amount_kopeks")
- return True
-
- except Exception as e:
- logger.error(f"Ошибка добавления колонки auto_assign_amount_kopeks: {e}")
- return False
-
-
-async def add_user_promo_group_auto_flag_column():
- logger.info("=== ДОБАВЛЕНИЕ ФЛАГА АВТО-ПРОМОГРУППЫ ДЛЯ ПОЛЬЗОВАТЕЛЕЙ ===")
-
- try:
- if await check_column_exists("users", "promo_group_auto_assigned"):
- logger.info("Колонка promo_group_auto_assigned уже существует в users")
- return True
-
- db_type = await get_database_type()
-
- if db_type == "sqlite":
- column_definition = "BOOLEAN NOT NULL DEFAULT 0"
- reset_sql = "UPDATE users SET promo_group_auto_assigned = 0 WHERE promo_group_auto_assigned IS NULL"
- elif db_type == "postgresql":
- column_definition = "BOOLEAN NOT NULL DEFAULT FALSE"
- reset_sql = "UPDATE users SET promo_group_auto_assigned = FALSE WHERE promo_group_auto_assigned IS NULL"
- elif db_type == "mysql":
- column_definition = "TINYINT(1) NOT NULL DEFAULT 0"
- reset_sql = "UPDATE users SET promo_group_auto_assigned = 0 WHERE promo_group_auto_assigned IS NULL"
- else:
- logger.error(f"Неподдерживаемый тип БД для promo_group_auto_assigned: {db_type}")
- return False
-
- async with engine.begin() as conn:
- await conn.execute(
- text(
- f"ALTER TABLE users ADD COLUMN promo_group_auto_assigned {column_definition}"
- )
- )
- await conn.execute(text(reset_sql))
-
- logger.info("Добавлена колонка users.promo_group_auto_assigned")
- return True
-
- except Exception as e:
- logger.error(f"Ошибка добавления колонки promo_group_auto_assigned: {e}")
- return False
-
-
async def add_welcome_text_is_enabled_column():
column_exists = await check_column_exists('welcome_texts', 'is_enabled')
if column_exists:
@@ -1586,18 +1511,6 @@ async def run_universal_migration():
else:
logger.warning("⚠️ Проблемы с настройкой промо групп")
- promo_auto_column_added = await add_promo_group_auto_assign_column()
- if promo_auto_column_added:
- logger.info("✅ Добавлено поле авто-выдачи в промо группах")
- else:
- logger.warning("⚠️ Не удалось добавить поле авто-выдачи в промо группах")
-
- user_auto_flag_added = await add_user_promo_group_auto_flag_column()
- if user_auto_flag_added:
- logger.info("✅ Добавлен флаг auto_assigned у пользователей")
- else:
- logger.warning("⚠️ Не удалось добавить флаг auto_assigned у пользователей")
-
logger.info("=== ОБНОВЛЕНИЕ ВНЕШНИХ КЛЮЧЕЙ ===")
fk_updated = await fix_foreign_keys_for_user_deletion()
if fk_updated:
@@ -1672,8 +1585,6 @@ async def check_migration_status():
"promo_groups_table": False,
"users_promo_group_column": False,
"promo_groups_period_discounts_column": False,
- "promo_groups_auto_assign_column": False,
- "users_promo_group_auto_flag_column": False,
}
status["has_made_first_topup_column"] = await check_column_exists('users', 'has_made_first_topup')
@@ -1687,8 +1598,6 @@ async def check_migration_status():
status["welcome_texts_is_enabled_column"] = await check_column_exists('welcome_texts', 'is_enabled')
status["users_promo_group_column"] = await check_column_exists('users', 'promo_group_id')
status["promo_groups_period_discounts_column"] = await check_column_exists('promo_groups', 'period_discounts')
- status["promo_groups_auto_assign_column"] = await check_column_exists('promo_groups', 'auto_assign_amount_kopeks')
- status["users_promo_group_auto_flag_column"] = await check_column_exists('users', 'promo_group_auto_assigned')
media_fields_exist = (
await check_column_exists('broadcast_history', 'has_media') and
@@ -1722,8 +1631,6 @@ async def check_migration_status():
"promo_groups_table": "Таблица промо-групп",
"users_promo_group_column": "Колонка promo_group_id у пользователей",
"promo_groups_period_discounts_column": "Колонка period_discounts у промо-групп",
- "promo_groups_auto_assign_column": "Колонка auto_assign_amount_kopeks у промо-групп",
- "users_promo_group_auto_flag_column": "Флаг auto_assigned у пользователей",
}
for check_key, check_status in status.items():
diff --git a/app/handlers/admin/promo_groups.py b/app/handlers/admin/promo_groups.py
index 567eead2..0546550e 100644
--- a/app/handlers/admin/promo_groups.py
+++ b/app/handlers/admin/promo_groups.py
@@ -1,5 +1,5 @@
import logging
-from decimal import Decimal, InvalidOperation, ROUND_HALF_UP
+import logging
from typing import Dict, Optional
from aiogram import Dispatcher, types, F
@@ -109,23 +109,6 @@ def _format_period_discounts_value(discounts: Dict[int, int]) -> str:
)
-def _format_auto_assign_line(texts, group: PromoGroup) -> Optional[str]:
- amount = getattr(group, "auto_assign_amount_kopeks", None)
- if not amount:
- return None
-
- return texts.t(
- "ADMIN_PROMO_GROUP_AUTO_ASSIGN_LINE",
- "🎯 Автовыдача с суммы: {amount}",
- ).format(amount=settings.format_price(amount))
-
-
-def _format_auto_assign_value(amount_kopeks: Optional[int]) -> str:
- if not amount_kopeks:
- return settings.format_price(0)
- return settings.format_price(amount_kopeks)
-
-
def _parse_period_discounts_input(value: str) -> Dict[int, int]:
cleaned = (value or "").strip()
@@ -157,29 +140,6 @@ def _parse_period_discounts_input(value: str) -> Dict[int, int]:
return discounts
-def _parse_auto_assign_amount_input(value: str) -> Optional[int]:
- cleaned = (value or "").strip()
-
- if not cleaned:
- raise ValueError
-
- normalized = cleaned.replace(" ", "").replace(",", ".")
-
- if normalized in {"0", "-", "нет", "off", "disable"}:
- return None
-
- try:
- decimal_value = Decimal(normalized)
- except (InvalidOperation, ValueError):
- raise ValueError
-
- if decimal_value <= 0:
- return None
-
- kopeks = (decimal_value * Decimal("100")).quantize(Decimal("1"), rounding=ROUND_HALF_UP)
- return int(kopeks)
-
-
async def _prompt_for_period_discounts(
message: types.Message,
state: FSMContext,
@@ -201,27 +161,6 @@ async def _prompt_for_period_discounts(
await message.answer(prompt_text)
-async def _prompt_for_auto_assign_amount(
- message: types.Message,
- state: FSMContext,
- prompt_key: str,
- default_text: str,
- *,
- current_value: Optional[str] = None,
-):
- data = await state.get_data()
- texts = get_texts(data.get("language", "ru"))
- prompt_text = texts.t(prompt_key, default_text)
-
- if current_value is not None:
- try:
- prompt_text = prompt_text.format(current=current_value)
- except KeyError:
- pass
-
- await message.answer(prompt_text)
-
-
@admin_required
@error_handler
async def show_promo_groups_menu(
@@ -252,18 +191,11 @@ async def show_promo_groups_menu(
group_lines = [
f"{'⭐' if group.is_default else '🎯'} {group.name}{default_suffix}",
_format_discount_line(texts, group),
- ]
-
- auto_line = _format_auto_assign_line(texts, group)
- if auto_line:
- group_lines.append(auto_line)
-
- group_lines.extend([
texts.t(
"ADMIN_PROMO_GROUPS_MEMBERS_COUNT",
"Участников: {count}",
).format(count=member_count),
- ])
+ ]
period_lines = _format_period_discounts_lines(texts, group, db_user.language)
group_lines.extend(period_lines)
@@ -333,18 +265,11 @@ async def show_promo_group_details(
"💳 Промогруппа: {name}",
).format(name=group.name),
_format_discount_line(texts, group),
- ]
-
- auto_line = _format_auto_assign_line(texts, group)
- if auto_line:
- lines.append(auto_line)
-
- lines.append(
texts.t(
"ADMIN_PROMO_GROUP_DETAILS_MEMBERS",
"Участников: {count}",
).format(count=member_count),
- )
+ ]
period_lines = _format_period_discounts_lines(texts, group, db_user.language)
lines.extend(period_lines)
@@ -539,39 +464,6 @@ async def process_create_group_period_discounts(
)
return
- await state.update_data(new_group_period_discounts=period_discounts)
- await state.set_state(AdminStates.creating_promo_group_auto_amount)
-
- await _prompt_for_auto_assign_amount(
- message,
- state,
- "ADMIN_PROMO_GROUP_CREATE_AUTO_ASSIGN_PROMPT",
- "Введите сумму пополнений (в рублях) для автоматической выдачи. Отправьте 0, если не нужно.",
- )
-
-
-@admin_required
-@error_handler
-async def process_create_group_auto_amount(
- message: types.Message,
- state: FSMContext,
- db_user,
- db: AsyncSession,
-):
- data = await state.get_data()
- texts = get_texts(data.get("language", db_user.language))
-
- try:
- auto_amount = _parse_auto_assign_amount_input(message.text)
- except ValueError:
- await message.answer(
- texts.t(
- "ADMIN_PROMO_GROUP_INVALID_AUTO_ASSIGN",
- "Введите корректную сумму или 0 для отключения.",
- )
- )
- return
-
try:
group = await create_promo_group(
db,
@@ -579,8 +471,7 @@ async def process_create_group_auto_amount(
traffic_discount_percent=data["new_group_traffic"],
server_discount_percent=data["new_group_servers"],
device_discount_percent=data["new_group_devices"],
- period_discounts=data.get("new_group_period_discounts"),
- auto_assign_amount_kopeks=auto_amount,
+ period_discounts=period_discounts,
)
except Exception as e:
logger.error(f"Не удалось создать промогруппу: {e}")
@@ -756,46 +647,6 @@ async def process_edit_group_period_discounts(
await state.clear()
return
- await state.update_data(edit_group_period_discounts=period_discounts)
- await state.set_state(AdminStates.editing_promo_group_auto_amount)
-
- await _prompt_for_auto_assign_amount(
- message,
- state,
- "ADMIN_PROMO_GROUP_EDIT_AUTO_ASSIGN_PROMPT",
- "Введите новую сумму (текущая: {current}). Отправьте 0, если без автовыдачи.",
- current_value=_format_auto_assign_value(getattr(group, "auto_assign_amount_kopeks", None)),
- )
-
-
-@admin_required
-@error_handler
-async def process_edit_group_auto_amount(
- message: types.Message,
- state: FSMContext,
- db_user,
- db: AsyncSession,
-):
- data = await state.get_data()
- texts = get_texts(data.get("language", db_user.language))
-
- try:
- auto_amount = _parse_auto_assign_amount_input(message.text)
- except ValueError:
- await message.answer(
- texts.t(
- "ADMIN_PROMO_GROUP_INVALID_AUTO_ASSIGN",
- "Введите корректную сумму или 0 для отключения.",
- )
- )
- return
-
- group = await get_promo_group_by_id(db, data.get("edit_group_id"))
- if not group:
- await message.answer("❌ Промогруппа не найдена")
- await state.clear()
- return
-
await update_promo_group(
db,
group,
@@ -803,8 +654,7 @@ async def process_edit_group_auto_amount(
traffic_discount_percent=data["edit_group_traffic"],
server_discount_percent=data["edit_group_servers"],
device_discount_percent=data["edit_group_devices"],
- period_discounts=data.get("edit_group_period_discounts"),
- auto_assign_amount_kopeks=auto_amount,
+ period_discounts=period_discounts,
)
await state.clear()
@@ -978,10 +828,6 @@ def register_handlers(dp: Dispatcher):
process_create_group_period_discounts,
AdminStates.creating_promo_group_period_discount,
)
- dp.message.register(
- process_create_group_auto_amount,
- AdminStates.creating_promo_group_auto_amount,
- )
dp.message.register(process_edit_group_name, AdminStates.editing_promo_group_name)
dp.message.register(
@@ -1000,7 +846,3 @@ def register_handlers(dp: Dispatcher):
process_edit_group_period_discounts,
AdminStates.editing_promo_group_period_discount,
)
- dp.message.register(
- process_edit_group_auto_amount,
- AdminStates.editing_promo_group_auto_amount,
- )
diff --git a/app/services/payment_service.py b/app/services/payment_service.py
index 17c39bd7..a761ef5c 100644
--- a/app/services/payment_service.py
+++ b/app/services/payment_service.py
@@ -30,7 +30,6 @@ from app.services.subscription_checkout_service import (
)
from app.services.mulenpay_service import MulenPayService
from app.services.pal24_service import Pal24Service, Pal24APIError
-from app.services.promo_group_service import maybe_assign_auto_promo_group
from app.database.crud.mulenpay import (
create_mulenpay_payment,
get_mulenpay_payment_by_local_id,
@@ -180,9 +179,7 @@ class PaymentService:
logger.error(f"Ошибка обработки реферального пополнения: {e}")
else:
logger.info(f"❌ Описание '{description_for_referral}' не подходит для реферальной логики")
-
- await maybe_assign_auto_promo_group(db, user, self.bot)
-
+
if self.bot:
try:
from app.services.admin_notification_service import AdminNotificationService
@@ -464,9 +461,7 @@ class PaymentService:
await process_referral_topup(db, user.id, updated_payment.amount_kopeks, self.bot)
except Exception as e:
logger.error(f"Ошибка обработки реферального пополнения YooKassa: {e}")
-
- await maybe_assign_auto_promo_group(db, user, self.bot)
-
+
if self.bot:
try:
from app.services.admin_notification_service import AdminNotificationService
@@ -533,8 +528,7 @@ class PaymentService:
user = await get_user_by_id(db, payment.user_id)
if user:
await add_user_balance(db, user, payment.amount_kopeks, f"Пополнение YooKassa: {payment.amount_kopeks//100}₽")
- await maybe_assign_auto_promo_group(db, user, self.bot)
-
+
logger.info(f"Успешно обработан платеж YooKassa {payment.yookassa_payment_id}: "
f"пользователь {payment.user_id} получил {payment.amount_kopeks/100}₽")
@@ -999,8 +993,6 @@ class PaymentService:
referral_error,
)
- await maybe_assign_auto_promo_group(db, user, self.bot)
-
await update_mulenpay_payment_status(
db,
payment=payment,
@@ -1190,8 +1182,6 @@ class PaymentService:
except Exception as referral_error:
logger.error("Ошибка обработки реферального пополнения Pal24: %s", referral_error)
- await maybe_assign_auto_promo_group(db, user, self.bot)
-
if self.bot:
try:
from app.services.admin_notification_service import AdminNotificationService
@@ -1448,9 +1438,7 @@ class PaymentService:
await process_referral_topup(db, user.id, amount_kopeks, self.bot)
except Exception as e:
logger.error(f"Ошибка обработки реферального пополнения CryptoBot: {e}")
-
- await maybe_assign_auto_promo_group(db, user, self.bot)
-
+
if self.bot:
try:
from app.services.admin_notification_service import AdminNotificationService
diff --git a/app/services/promo_group_service.py b/app/services/promo_group_service.py
deleted file mode 100644
index 02ad4dbc..00000000
--- a/app/services/promo_group_service.py
+++ /dev/null
@@ -1,77 +0,0 @@
-import logging
-from datetime import datetime
-from typing import Optional
-
-from aiogram import Bot
-from sqlalchemy.ext.asyncio import AsyncSession
-
-from app.config import settings
-from app.database.crud.promo_group import get_auto_assign_promo_group
-from app.database.crud.transaction import get_user_total_completed_deposits
-from app.database.models import PromoGroup, User
-from app.localization.texts import get_texts
-
-logger = logging.getLogger(__name__)
-
-
-def _format_total_amount(total_amount_kopeks: int) -> str:
- return settings.format_price(total_amount_kopeks)
-
-
-async def maybe_assign_auto_promo_group(
- db: AsyncSession,
- user: User,
- bot: Optional[Bot] = None,
-) -> Optional[PromoGroup]:
- """Назначает промогруппу автоматически при достижении нужной суммы пополнений."""
- try:
- if getattr(user, "promo_group_auto_assigned", False):
- return None
-
- total_amount_kopeks = await get_user_total_completed_deposits(db, user.id)
- target_group = await get_auto_assign_promo_group(db, total_amount_kopeks)
-
- if not target_group or target_group.id == user.promo_group_id:
- return None
-
- user.promo_group_id = target_group.id
- user.promo_group = target_group
- user.promo_group_auto_assigned = True
- user.updated_at = datetime.utcnow()
-
- await db.commit()
- await db.refresh(user)
-
- logger.info(
- "Автоматически назначена промогруппа '%s' пользователю %s (сумма пополнений: %s)",
- target_group.name,
- user.telegram_id,
- _format_total_amount(total_amount_kopeks),
- )
-
- if bot:
- try:
- texts = get_texts(user.language)
- message = texts.t(
- "PROMO_GROUP_AUTO_ASSIGN_NOTIFICATION",
- "🎉 Вы автоматически переведены в промогруппу «{name}» за пополнения на {amount}.",
- ).format(name=target_group.name, amount=_format_total_amount(total_amount_kopeks))
- await bot.send_message(user.telegram_id, message, parse_mode="HTML")
- except Exception as notify_error:
- logger.error(
- "Ошибка отправки уведомления об автоназначении промогруппы пользователю %s: %s",
- user.telegram_id,
- notify_error,
- )
-
- return target_group
-
- except Exception as error:
- logger.error(
- "Ошибка автоматического назначения промогруппы пользователю %s: %s",
- getattr(user, "telegram_id", "unknown"),
- error,
- exc_info=True,
- )
- await db.rollback()
- return None
diff --git a/app/services/tribute_service.py b/app/services/tribute_service.py
index 8dd427f4..6d5de2eb 100644
--- a/app/services/tribute_service.py
+++ b/app/services/tribute_service.py
@@ -14,7 +14,6 @@ from app.database.crud.transaction import (
from app.database.crud.user import get_user_by_telegram_id, add_user_balance
from app.external.tribute import TributeService as TributeAPI
from app.services.payment_service import PaymentService
-from app.services.promo_group_service import maybe_assign_auto_promo_group
logger = logging.getLogger(__name__)
@@ -140,10 +139,8 @@ class TributeService:
if not user.has_made_first_topup:
user.has_made_first_topup = True
logger.info(f"Отмечен первый топап для пользователя {user_telegram_id}")
-
- await maybe_assign_auto_promo_group(session, user, self.bot)
-
-
+
+
try:
from app.services.admin_notification_service import AdminNotificationService
notification_service = AdminNotificationService(self.bot)
@@ -336,13 +333,11 @@ class TributeService:
old_balance = user.balance_kopeks
user.balance_kopeks += amount_kopeks
user.updated_at = datetime.utcnow()
-
+
await session.commit()
-
- await maybe_assign_auto_promo_group(session, user, self.bot)
-
+
logger.info(f"💰 ПРИНУДИТЕЛЬНО обновлен баланс: {old_balance} -> {user.balance_kopeks} коп")
-
+
await self._send_success_notification(user_id, amount_kopeks)
logger.info(f"✅ Принудительно обработан платеж {payment_id}")
diff --git a/app/states.py b/app/states.py
index 940986d2..0073a4d4 100644
--- a/app/states.py
+++ b/app/states.py
@@ -69,14 +69,12 @@ class AdminStates(StatesGroup):
creating_promo_group_server_discount = State()
creating_promo_group_device_discount = State()
creating_promo_group_period_discount = State()
- creating_promo_group_auto_amount = State()
editing_promo_group_name = State()
editing_promo_group_traffic_discount = State()
editing_promo_group_server_discount = State()
editing_promo_group_device_discount = State()
editing_promo_group_period_discount = State()
- editing_promo_group_auto_amount = State()
editing_squad_price = State()
editing_traffic_price = State()
diff --git a/locales/en.json b/locales/en.json
index 51508f0d..419dbe95 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -141,7 +141,6 @@
"ADMIN_PROMO_GROUPS_DEFAULT_LABEL": " (default)",
"ADMIN_PROMO_GROUPS_MEMBERS_COUNT": "Members: {count}",
"ADMIN_PROMO_GROUPS_EMPTY": "No promo groups found.",
- "ADMIN_PROMO_GROUP_AUTO_ASSIGN_LINE": "🎯 Auto assignment from: {amount}",
"CREATE_TICKET_BUTTON": "🎫 Create ticket",
"MY_TICKETS_BUTTON": "📋 My tickets",
"CONTACT_SUPPORT_BUTTON": "💬 Contact support",
@@ -227,10 +226,8 @@
"ADMIN_PROMO_GROUP_CREATE_SERVERS_PROMPT": "Enter server discount (0-100):",
"ADMIN_PROMO_GROUP_CREATE_DEVICES_PROMPT": "Enter device discount (0-100):",
"ADMIN_PROMO_GROUP_CREATE_PERIOD_PROMPT": "Enter subscription period discounts (e.g. 30:10, 90:15). Send 0 if none.",
- "ADMIN_PROMO_GROUP_CREATE_AUTO_ASSIGN_PROMPT": "Enter the top-up amount (in rubles) for automatic assignment. Send 0 to disable.",
"ADMIN_PROMO_GROUP_INVALID_PERCENT": "Enter a number from 0 to 100.",
"ADMIN_PROMO_GROUP_INVALID_PERIOD_DISCOUNTS": "Enter period:discount pairs separated by commas, e.g. 30:10, 90:15, or 0.",
- "ADMIN_PROMO_GROUP_INVALID_AUTO_ASSIGN": "Enter a valid amount or 0 to disable.",
"ADMIN_PROMO_GROUP_CREATED": "Promo group “{name}” created.",
"ADMIN_PROMO_GROUP_CREATED_BACK_BUTTON": "↩️ Back to promo groups",
"ADMIN_PROMO_GROUP_EDIT_NAME_PROMPT": "Enter a new name (current: {name}):",
@@ -238,7 +235,6 @@
"ADMIN_PROMO_GROUP_EDIT_SERVERS_PROMPT": "Enter new server discount (0-100):",
"ADMIN_PROMO_GROUP_EDIT_DEVICES_PROMPT": "Enter new device discount (0-100):",
"ADMIN_PROMO_GROUP_EDIT_PERIOD_PROMPT": "Enter new period discounts (current: {current}). Send 0 if none.",
- "ADMIN_PROMO_GROUP_EDIT_AUTO_ASSIGN_PROMPT": "Enter a new amount (current: {current}). Send 0 to disable.",
"ADMIN_PROMO_GROUP_UPDATED": "Promo group “{name}” updated.",
"ADMIN_PROMO_GROUP_MEMBERS_TITLE": "👥 Members of {name}",
"ADMIN_PROMO_GROUP_MEMBERS_EMPTY": "This group has no members yet.",
@@ -267,7 +263,6 @@
"PROMO_GROUP_DISCOUNT_DEVICES": "📱 Extra devices: {percent}%",
"PROMO_GROUP_PERIOD_DISCOUNTS_HEADER": "⏳ Long-term period discounts:",
"PROMO_GROUP_PERIOD_DISCOUNT_ITEM": "{period} — {percent}%",
- "PROMO_GROUP_AUTO_ASSIGN_NOTIFICATION": "🎉 You have been automatically moved to the promo group “{name}” for topping up {amount}.",
"CHANGE_DEVICES_CONFIRM": "\n📱 Confirm change\n\nCurrent amount: {current_devices} devices\nNew amount: {new_devices} devices\n\nAction: {action}\n💰 {cost}\n\nApply this change?\n",
"CHANGE_DEVICES_INFO": "\n📱 Adjust device limit\n\nCurrent limit: {current_devices} devices\n\nChoose the new number of devices:\n\n💡 Important:\n• Increasing — extra charge proportional to the remaining time\n• Decreasing — funds are not refunded\n",
"CHANGE_DEVICES_SUCCESS_DECREASE": "\n✅ Device limit decreased!\n\n📱 Was: {old_count} → Now: {new_count}\nℹ️ Payments are not refunded\n",
diff --git a/locales/ru.json b/locales/ru.json
index ac1c6d0d..e69b9d92 100644
--- a/locales/ru.json
+++ b/locales/ru.json
@@ -19,7 +19,6 @@
"ADMIN_PROMO_GROUPS_DEFAULT_LABEL": " (базовая)",
"ADMIN_PROMO_GROUPS_MEMBERS_COUNT": "Участников: {count}",
"ADMIN_PROMO_GROUPS_EMPTY": "Промогруппы не найдены.",
- "ADMIN_PROMO_GROUP_AUTO_ASSIGN_LINE": "🎯 Автовыдача с суммы: {amount}",
"CREATE_TICKET_BUTTON": "🎫 Создать тикет",
"MY_TICKETS_BUTTON": "📋 Мои тикеты",
"CONTACT_SUPPORT_BUTTON": "💬 Связаться с поддержкой",
@@ -105,10 +104,8 @@
"ADMIN_PROMO_GROUP_CREATE_SERVERS_PROMPT": "Введите скидку на серверы (0-100):",
"ADMIN_PROMO_GROUP_CREATE_DEVICES_PROMPT": "Введите скидку на устройства (0-100):",
"ADMIN_PROMO_GROUP_CREATE_PERIOD_PROMPT": "Введите скидки на периоды подписки (например, 30:10, 90:15). Отправьте 0, если без скидок.",
- "ADMIN_PROMO_GROUP_CREATE_AUTO_ASSIGN_PROMPT": "Введите сумму пополнений (в рублях) для автоматической выдачи. Отправьте 0, если без автовыдачи.",
"ADMIN_PROMO_GROUP_INVALID_PERCENT": "Введите число от 0 до 100.",
"ADMIN_PROMO_GROUP_INVALID_PERIOD_DISCOUNTS": "Введите пары период:скидка через запятую, например 30:10, 90:15, или 0.",
- "ADMIN_PROMO_GROUP_INVALID_AUTO_ASSIGN": "Введите корректную сумму или 0 для отключения.",
"ADMIN_PROMO_GROUP_CREATED": "Промогруппа «{name}» создана.",
"ADMIN_PROMO_GROUP_CREATED_BACK_BUTTON": "↩️ К промогруппам",
"ADMIN_PROMO_GROUP_EDIT_NAME_PROMPT": "Введите новое название промогруппы (текущее: {name}):",
@@ -116,7 +113,6 @@
"ADMIN_PROMO_GROUP_EDIT_SERVERS_PROMPT": "Введите новую скидку на серверы (0-100):",
"ADMIN_PROMO_GROUP_EDIT_DEVICES_PROMPT": "Введите новую скидку на устройства (0-100):",
"ADMIN_PROMO_GROUP_EDIT_PERIOD_PROMPT": "Введите новые скидки на периоды (текущие: {current}). Отправьте 0, если без скидок.",
- "ADMIN_PROMO_GROUP_EDIT_AUTO_ASSIGN_PROMPT": "Введите новую сумму (текущая: {current}). Отправьте 0, если без автовыдачи.",
"ADMIN_PROMO_GROUP_UPDATED": "Промогруппа «{name}» обновлена.",
"ADMIN_PROMO_GROUP_MEMBERS_TITLE": "👥 Участники группы {name}",
"ADMIN_PROMO_GROUP_MEMBERS_EMPTY": "В этой группе пока нет участников.",
@@ -150,7 +146,6 @@
"PROMO_GROUP_DISCOUNT_DEVICES": "📱 Доп. устройства: {percent}%",
"PROMO_GROUP_PERIOD_DISCOUNTS_HEADER": "⏳ Скидки за длительный период:",
"PROMO_GROUP_PERIOD_DISCOUNT_ITEM": "{period} — {percent}%",
- "PROMO_GROUP_AUTO_ASSIGN_NOTIFICATION": "🎉 Вы автоматически переведены в промогруппу «{name}» за пополнения на {amount}.",
"CANCEL": "❌ Отмена",
"CHANGE_DEVICES_BUTTON": "📱 Изменить устройства",
"CHANGE_DEVICES_CONFIRM": "\n 📱 Подтверждение изменения\n\n Текущее количество: {current_devices} устройств\n Новое количество: {new_devices} устройств\n\n Действие: {action}\n 💰 {cost}\n\n Подтвердить изменение?\n ",