import csv from datetime import datetime from io import StringIO from aiogram.types import BufferedInputFile from sqlalchemy import func, join, select from sqlalchemy.ext.asyncio import AsyncSession from database.models import Key, Payment, Referral, Tariff, User async def export_users_csv(session: AsyncSession) -> BufferedInputFile: query = select( User.tg_id, User.username, User.first_name, User.last_name, User.language_code, User.is_bot, User.balance, User.trial, User.created_at, ).order_by(User.created_at.asc()) result = await session.execute(query) users = result.all() buffer = StringIO() writer = csv.writer(buffer) writer.writerow( [ "tg_id", "username", "first_name", "last_name", "language_code", "is_bot", "balance", "trial", "created_at", ] ) for user in users: writer.writerow(user) buffer.seek(0) return BufferedInputFile( file=buffer.getvalue().encode("utf-8-sig"), filename="users_export.csv" ) async def export_payments_csv(session: AsyncSession) -> BufferedInputFile: j = join(User, Payment, User.tg_id == Payment.tg_id) query = ( select( User.tg_id, User.username, User.first_name, User.last_name, Payment.amount, Payment.payment_system, Payment.status, Payment.created_at, ) .select_from(j) .order_by(Payment.created_at.asc()) ) result = await session.execute(query) payments = result.all() return _export_payments_csv(payments, "payments_export.csv") async def export_user_payments_csv( tg_id: int, session: AsyncSession ) -> BufferedInputFile: j = join(User, Payment, User.tg_id == Payment.tg_id) query = ( select( User.tg_id, User.username, User.first_name, User.last_name, Payment.amount, Payment.payment_system, Payment.status, Payment.created_at, ) .select_from(j) .where(User.tg_id == tg_id) .order_by(Payment.created_at.asc()) ) result = await session.execute(query) payments = result.all() return _export_payments_csv(payments, f"payments_export_{tg_id}.csv") def _export_payments_csv(payments, filename: str) -> BufferedInputFile: buffer = StringIO() writer = csv.writer(buffer) writer.writerow( [ "tg_id", "username", "first_name", "last_name", "amount", "payment_system", "status", "created_at", ] ) for payment in payments: writer.writerow(payment) buffer.seek(0) return BufferedInputFile( file=buffer.getvalue().encode("utf-8-sig"), filename=filename ) async def export_referrals_csv( referrer_tg_id: int, session: AsyncSession ) -> BufferedInputFile | None: j = join(Referral, User, Referral.referred_tg_id == User.tg_id) query = ( select( Referral.referred_tg_id, func.coalesce(User.first_name, ""), func.coalesce(User.last_name, ""), func.coalesce(User.username, ""), ) .select_from(j) .where(Referral.referrer_tg_id == referrer_tg_id) .order_by(Referral.referred_tg_id.asc()) ) result = await session.execute(query) rows = result.all() if not rows: return None output = StringIO() writer = csv.writer(output, delimiter=";") writer.writerow(["Приглашённый (tg_id)", "Имя"]) for invited_id, first_name, last_name, username in rows: full_name = first_name.strip() or username or str(invited_id) if last_name: full_name = f"{full_name} {last_name}" writer.writerow([invited_id, full_name.strip()]) output.seek(0) return BufferedInputFile( file=output.getvalue().encode("utf-8"), filename=f"referrals_{referrer_tg_id}.csv", ) async def export_hot_leads_csv(session: AsyncSession) -> BufferedInputFile: users_alias = User.__table__.alias("u") payments_alias = Payment.__table__.alias("p") keys_alias = Key.__table__.alias("k") j = users_alias.join( payments_alias, users_alias.c.tg_id == payments_alias.c.tg_id ).outerjoin(keys_alias, users_alias.c.tg_id == keys_alias.c.tg_id) query = ( select( users_alias.c.tg_id, users_alias.c.username, users_alias.c.first_name, users_alias.c.last_name, users_alias.c.updated_at, ) .select_from(j) .where(payments_alias.c.status == "success", keys_alias.c.tg_id is None) .distinct() .order_by(users_alias.c.updated_at.desc()) ) result = await session.execute(query) users = result.all() buffer = StringIO() writer = csv.writer(buffer) writer.writerow(["tg_id", "username", "first_name", "last_name", "updated_at"]) for user in users: writer.writerow(user) buffer.seek(0) return BufferedInputFile( file=buffer.getvalue().encode("utf-8-sig"), filename="hot_leads_export.csv" ) async def export_keys_csv(session: AsyncSession) -> BufferedInputFile: j = join(Key, Tariff, Key.tariff_id == Tariff.id, isouter=True) query = ( select( Key.tg_id, Key.client_id, Key.email, Key.created_at, Key.expiry_time, Key.key, Key.server_id, Key.is_frozen, Key.alias, Tariff.name.label("tariff_name"), ) .select_from(j) .order_by(Key.created_at.asc()) ) result = await session.execute(query) keys = result.all() buffer = StringIO() writer = csv.writer(buffer) writer.writerow( [ "tg_id", "client_id", "email", "created_at", "expiry_time", "key", "server_id", "is_frozen", "alias", "tariff", ] ) for row in keys: created_at = ( datetime.utcfromtimestamp(row.created_at / 1000).strftime( "%Y-%m-%d %H:%M:%S" ) if row.created_at else "" ) expiry_time = ( datetime.utcfromtimestamp(row.expiry_time / 1000).strftime( "%Y-%m-%d %H:%M:%S" ) if row.expiry_time else "" ) tariff = row.tariff_name or "—" writer.writerow( [ row.tg_id, row.client_id, row.email, created_at, expiry_time, row.key, row.server_id, row.is_frozen, row.alias or "", tariff, ] ) buffer.seek(0) return BufferedInputFile( file=buffer.getvalue().encode("utf-8-sig"), filename="keys_export.csv" )