diff --git a/app/services/referral_service.py b/app/services/referral_service.py
index bbf6e810..2302cf45 100644
--- a/app/services/referral_service.py
+++ b/app/services/referral_service.py
@@ -89,16 +89,64 @@ async def process_referral_topup(
logger.info(f"Пользователь {user_id} не является рефералом")
return True
- if topup_amount_kopeks < settings.REFERRAL_MINIMUM_TOPUP_KOPEKS:
- logger.info(f"Пополнение {user_id} на {topup_amount_kopeks/100}₽ меньше минимума")
- return True
-
referrer = await get_user_by_id(db, user.referred_by_id)
if not referrer:
logger.error(f"Реферер {user.referred_by_id} не найден")
return False
-
+
+ qualifies_for_first_bonus = (
+ topup_amount_kopeks >= settings.REFERRAL_MINIMUM_TOPUP_KOPEKS
+ )
+ commission_amount = 0
+ if settings.REFERRAL_COMMISSION_PERCENT > 0:
+ commission_amount = int(
+ topup_amount_kopeks * settings.REFERRAL_COMMISSION_PERCENT / 100
+ )
+
if not user.has_made_first_topup:
+ if not qualifies_for_first_bonus:
+ logger.info(
+ "Пополнение %s на %s₽ меньше минимума для первого бонуса, но комиссия будет начислена",
+ user_id,
+ topup_amount_kopeks / 100,
+ )
+
+ if commission_amount > 0:
+ await add_user_balance(
+ db,
+ referrer,
+ commission_amount,
+ f"Комиссия {settings.REFERRAL_COMMISSION_PERCENT}% с пополнения {user.full_name}",
+ bot=bot,
+ )
+
+ await create_referral_earning(
+ db=db,
+ user_id=referrer.id,
+ referral_id=user.id,
+ amount_kopeks=commission_amount,
+ reason="referral_commission_topup",
+ )
+
+ logger.info(
+ "💰 Комиссия с пополнения: %s получил %s₽ (до первого бонуса)",
+ referrer.telegram_id,
+ commission_amount / 100,
+ )
+
+ if bot:
+ commission_notification = (
+ f"💰 Реферальная комиссия!\n\n"
+ f"Ваш реферал {user.full_name} пополнил баланс на "
+ f"{settings.format_price(topup_amount_kopeks)}\n\n"
+ f"🎁 Ваша комиссия ({settings.REFERRAL_COMMISSION_PERCENT}%): "
+ f"{settings.format_price(commission_amount)}\n\n"
+ f"💎 Средства зачислены на ваш баланс."
+ )
+ await send_referral_notification(bot, referrer.telegram_id, commission_notification)
+
+ return True
+
user.has_made_first_topup = True
await db.commit()
@@ -161,36 +209,33 @@ async def process_referral_topup(
await send_referral_notification(bot, referrer.telegram_id, inviter_bonus_notification)
else:
- if settings.REFERRAL_COMMISSION_PERCENT > 0:
- commission_amount = int(topup_amount_kopeks * settings.REFERRAL_COMMISSION_PERCENT / 100)
-
- if commission_amount > 0:
- await add_user_balance(
- db, referrer, commission_amount,
- f"Комиссия {settings.REFERRAL_COMMISSION_PERCENT}% с пополнения {user.full_name}",
- bot=bot
+ if commission_amount > 0:
+ await add_user_balance(
+ db, referrer, commission_amount,
+ f"Комиссия {settings.REFERRAL_COMMISSION_PERCENT}% с пополнения {user.full_name}",
+ bot=bot
+ )
+
+ await create_referral_earning(
+ db=db,
+ user_id=referrer.id,
+ referral_id=user.id,
+ amount_kopeks=commission_amount,
+ reason="referral_commission_topup"
+ )
+
+ logger.info(f"💰 Комиссия с пополнения: {referrer.telegram_id} получил {commission_amount/100}₽")
+
+ if bot:
+ commission_notification = (
+ f"💰 Реферальная комиссия!\n\n"
+ f"Ваш реферал {user.full_name} пополнил баланс на "
+ f"{settings.format_price(topup_amount_kopeks)}\n\n"
+ f"🎁 Ваша комиссия ({settings.REFERRAL_COMMISSION_PERCENT}%): "
+ f"{settings.format_price(commission_amount)}\n\n"
+ f"💎 Средства зачислены на ваш баланс."
)
-
- await create_referral_earning(
- db=db,
- user_id=referrer.id,
- referral_id=user.id,
- amount_kopeks=commission_amount,
- reason="referral_commission_topup"
- )
-
- logger.info(f"💰 Комиссия с пополнения: {referrer.telegram_id} получил {commission_amount/100}₽")
-
- if bot:
- commission_notification = (
- f"💰 Реферальная комиссия!\n\n"
- f"Ваш реферал {user.full_name} пополнил баланс на "
- f"{settings.format_price(topup_amount_kopeks)}\n\n"
- f"🎁 Ваша комиссия ({settings.REFERRAL_COMMISSION_PERCENT}%): "
- f"{settings.format_price(commission_amount)}\n\n"
- f"💎 Средства зачислены на ваш баланс."
- )
- await send_referral_notification(bot, referrer.telegram_id, commission_notification)
+ await send_referral_notification(bot, referrer.telegram_id, commission_notification)
return True
diff --git a/tests/services/test_referral_service.py b/tests/services/test_referral_service.py
new file mode 100644
index 00000000..c59c5bd5
--- /dev/null
+++ b/tests/services/test_referral_service.py
@@ -0,0 +1,67 @@
+from pathlib import Path
+import sys
+from types import SimpleNamespace
+from unittest.mock import AsyncMock
+
+import pytest
+
+ROOT_DIR = Path(__file__).resolve().parents[2]
+if str(ROOT_DIR) not in sys.path:
+ sys.path.insert(0, str(ROOT_DIR))
+
+from app.services import referral_service # noqa: E402
+
+
+@pytest.mark.asyncio
+async def test_commission_accrues_before_minimum_first_topup(monkeypatch):
+ user = SimpleNamespace(
+ id=1,
+ telegram_id=101,
+ full_name="Test User",
+ referred_by_id=2,
+ has_made_first_topup=False,
+ )
+ referrer = SimpleNamespace(
+ id=2,
+ telegram_id=202,
+ full_name="Referrer",
+ )
+
+ db = SimpleNamespace(
+ commit=AsyncMock(),
+ execute=AsyncMock(),
+ )
+
+ get_user_mock = AsyncMock(side_effect=[user, referrer])
+ monkeypatch.setattr(referral_service, "get_user_by_id", get_user_mock)
+ add_user_balance_mock = AsyncMock()
+ monkeypatch.setattr(referral_service, "add_user_balance", add_user_balance_mock)
+ create_referral_earning_mock = AsyncMock()
+ monkeypatch.setattr(referral_service, "create_referral_earning", create_referral_earning_mock)
+
+ monkeypatch.setattr(referral_service.settings, "REFERRAL_MINIMUM_TOPUP_KOPEKS", 20000)
+ monkeypatch.setattr(referral_service.settings, "REFERRAL_FIRST_TOPUP_BONUS_KOPEKS", 5000)
+ monkeypatch.setattr(referral_service.settings, "REFERRAL_INVITER_BONUS_KOPEKS", 10000)
+ monkeypatch.setattr(referral_service.settings, "REFERRAL_COMMISSION_PERCENT", 25)
+
+ topup_amount = 15000
+
+ result = await referral_service.process_referral_topup(db, user.id, topup_amount)
+
+ assert result is True
+ assert user.has_made_first_topup is False
+
+ add_user_balance_mock.assert_awaited_once()
+ add_call = add_user_balance_mock.await_args
+ assert add_call.args[1] is referrer
+ assert add_call.args[2] == 3750
+ assert "Комиссия" in add_call.args[3]
+ assert add_call.kwargs.get("bot") is None
+
+ create_referral_earning_mock.assert_awaited_once()
+ earning_call = create_referral_earning_mock.await_args
+ assert earning_call.kwargs["amount_kopeks"] == 3750
+ assert earning_call.kwargs["reason"] == "referral_commission_topup"
+
+ db.commit.assert_not_awaited()
+ db.execute.assert_not_awaited()