89 lines
3.5 KiB
Python
89 lines
3.5 KiB
Python
import logging
|
|
import aiosqlite
|
|
from datetime import datetime, timezone
|
|
from typing import Optional, Dict, Callable, Any, Tuple
|
|
|
|
from aiogram import Bot
|
|
from config.settings import Settings
|
|
from db.database import get_promo_code_by_code, increment_promo_activation, get_db_connection_manager, _setup_db_connection
|
|
from .subscription_service import SubscriptionService
|
|
from bot.middlewares.i18n import JsonI18n
|
|
|
|
|
|
class PromoCodeService:
|
|
|
|
def __init__(self, db_conn_provider: Callable[[], Any], settings: Settings,
|
|
subscription_service: SubscriptionService, bot: Bot,
|
|
i18n: JsonI18n):
|
|
self.db_conn_provider = db_conn_provider
|
|
self.settings = settings
|
|
self.subscription_service = subscription_service
|
|
self.bot = bot
|
|
self.i18n = i18n
|
|
|
|
async def apply_promo_code(self, user_id: int, code_input: str,
|
|
user_lang: str) -> Tuple[bool, str]:
|
|
"""
|
|
Applies a promo code for a user.
|
|
Returns: (success_status: bool, message_text_for_user: str)
|
|
"""
|
|
_ = lambda k, **kw: self.i18n.gettext(user_lang, k, **kw)
|
|
code_input_upper = code_input.strip().upper()
|
|
|
|
async with self.db_conn_provider() as db:
|
|
await _setup_db_connection(db)
|
|
try:
|
|
promo_data = await get_promo_code_by_code(code_input_upper,
|
|
db_conn=db)
|
|
|
|
if not promo_data:
|
|
return False, _("promo_code_not_found",
|
|
code=code_input_upper)
|
|
|
|
if promo_data['current_activations'] >= promo_data[
|
|
'max_activations']:
|
|
return False, _("promo_code_max_activations_reached",
|
|
code=code_input_upper)
|
|
|
|
active_sub = await self.subscription_service.get_active_subscription(
|
|
user_id)
|
|
if not active_sub:
|
|
return False, _("promo_code_no_active_subscription")
|
|
|
|
bonus_days = promo_data['bonus_days']
|
|
|
|
new_end_date = await self.subscription_service.extend_active_subscription_days(
|
|
user_id=user_id,
|
|
bonus_days=bonus_days,
|
|
db_conn=db,
|
|
reason=f"promo code {code_input_upper}")
|
|
|
|
if new_end_date:
|
|
|
|
activation_success = await increment_promo_activation(
|
|
promo_data['promo_code_id'],
|
|
user_id,
|
|
db_conn=db,
|
|
payment_id=None)
|
|
if activation_success:
|
|
await db.commit()
|
|
return True, _(
|
|
"promo_code_applied_success",
|
|
code=code_input_upper,
|
|
bonus_days=bonus_days,
|
|
new_end_date=new_end_date.strftime('%Y-%m-%d'))
|
|
else:
|
|
|
|
await db.rollback()
|
|
return False, _("promo_code_invalid_or_expired")
|
|
else:
|
|
await db.rollback()
|
|
return False, _("error_applying_promo_bonus")
|
|
|
|
except Exception as e:
|
|
logging.error(
|
|
f"Error applying promo code {code_input_upper} for user {user_id}: {e}",
|
|
exc_info=True)
|
|
await db.rollback()
|
|
return False, _("error_try_again")
|