Export user payments to CSV

This commit is contained in:
Vladless
2025-12-26 18:53:23 +03:00
parent 79ddde90ca
commit f32ebc95cd
4 changed files with 118 additions and 0 deletions
+31
View File
@@ -180,3 +180,34 @@ async def cancel_expired_pending_payments(session: AsyncSession) -> int:
await session.commit()
affected = res.rowcount or 0
return affected
async def get_all_payments(
session: AsyncSession,
tg_id: int,
statuses: list[str] | None = None,
) -> list[dict]:
query = select(Payment).where(Payment.tg_id == tg_id)
if statuses:
query = query.where(Payment.status.in_(statuses))
query = query.order_by(Payment.created_at.desc())
result = await session.execute(query)
payments = result.scalars().all()
return [
{
"id": p.id,
"tg_id": p.tg_id,
"amount": p.amount,
"currency": p.currency,
"status": p.status,
"payment_system": p.payment_system,
"payment_id": p.payment_id,
"created_at": p.created_at,
"metadata": p.metadata_,
"original_amount": p.original_amount,
}
for p in payments
]
+6
View File
@@ -142,6 +142,12 @@ async def build_users_balance_kb(session: AsyncSession, tg_id: int) -> InlineKey
callback_data=AdminUserEditorCallback(action="users_balance_set", tg_id=tg_id).pack(),
)
)
builder.row(
InlineKeyboardButton(
text="Выгрузить платежи",
callback_data=AdminUserEditorCallback(action="users_balance_export", tg_id=tg_id).pack(),
)
)
builder.row(build_editor_back_btn(tg_id, True))
+16
View File
@@ -7,6 +7,7 @@ from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from database import get_balance, set_user_balance, update_balance
from utils.csv_export import export_user_all_payments_csv
from database.models import Payment
from database.payments import add_payment
from filters.admin import IsAdminFilter
@@ -92,6 +93,21 @@ async def handle_balance_change(
)
@router.callback_query(
AdminUserEditorCallback.filter(F.action == "users_balance_export"),
IsAdminFilter(),
)
async def handle_balance_export(
callback_query: CallbackQuery,
callback_data: AdminUserEditorCallback,
session: AsyncSession,
):
tg_id = callback_data.tg_id
csv_file = await export_user_all_payments_csv(tg_id=tg_id, session=session)
await callback_query.message.answer_document(csv_file)
await callback_query.answer()
@router.callback_query(
AdminUserEditorCallback.filter(F.action == "users_balance_add"),
IsAdminFilter(),
+65
View File
@@ -6,6 +6,7 @@ from io import StringIO
from aiogram.types import BufferedInputFile
from sqlalchemy import exists, func, join, not_, select
from sqlalchemy.ext.asyncio import AsyncSession
import json
from core.constants import PAYMENT_SYSTEMS_EXCLUDED
from database.models import Key, Payment, Referral, Tariff, User
@@ -258,3 +259,67 @@ async def export_keys_csv(session: AsyncSession) -> BufferedInputFile:
buffer.seek(0)
return BufferedInputFile(file=buffer.getvalue().encode("utf-8-sig"), filename="keys_export.csv")
async def export_user_all_payments_csv(tg_id: int, session: AsyncSession) -> BufferedInputFile:
query = (
select(
Payment.id,
Payment.tg_id,
Payment.payment_id,
Payment.amount,
Payment.currency,
Payment.payment_system,
Payment.status,
Payment.original_amount,
Payment.created_at,
)
.where(Payment.tg_id == tg_id)
.order_by(Payment.created_at.asc())
)
result = await session.execute(query)
rows = result.all()
buffer = StringIO()
writer = csv.writer(buffer)
writer.writerow([
"id",
"tg_id",
"payment_id",
"amount",
"currency",
"payment_system",
"status",
"original_amount",
"created_at",
])
for (
internal_id,
user_tg_id,
external_payment_id,
amount,
currency,
payment_system,
status,
original_amount,
created_at,
) in rows:
writer.writerow([
internal_id,
user_tg_id,
external_payment_id or "",
amount,
currency,
payment_system,
status,
original_amount if original_amount is not None else "",
created_at,
])
buffer.seek(0)
return BufferedInputFile(
file=buffer.getvalue().encode("utf-8-sig"),
filename=f"user_{tg_id}_payments_full.csv",
)