from datetime import datetime import sys from fastapi import APIRouter, Depends, HTTPException from fastapi.exceptions import HTTPException from app.services import DatabaseManager from sqlalchemy.exc import SQLAlchemyError from instance.configdb import get_database_manager from pydantic import BaseModel from typing import Optional from uuid import UUID import logging logger = logging.getLogger(__name__) if not logger.handlers: handler = logging.StreamHandler(sys.stdout) handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')) logger.addHandler(handler) logger.setLevel(logging.INFO) logger.propagate = False router = APIRouter() # Модели запросов и ответов class CreateUserRequest(BaseModel): telegram_id: int invited_by: Optional[int] = None class UserResponse(BaseModel): telegram_id: int username: Optional[str] balance: float invited_by: Optional[int] = None created_at: str updated_at: str class AddReferal(BaseModel): invited_id: int @router.post("/user/create", response_model=UserResponse, summary="Создать пользователя") async def create_user( request: CreateUserRequest, db_manager: DatabaseManager = Depends(get_database_manager) ): """ Создание пользователя через Telegram ID. """ try: user = await db_manager.create_user(request.telegram_id,request.invited_by) if user == None: raise HTTPException(status_code=500, detail="Failed to create user") return UserResponse( telegram_id=user.telegram_id, username=user.username, balance=user.balance, invited_by=user.invited_by if user.invited_by is not None else None, created_at=user.created_at.isoformat(), updated_at=user.updated_at.isoformat() ) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/user/{telegram_id}", response_model=UserResponse, summary="Получить информацию о пользователе") async def get_user( telegram_id: int, db_manager: DatabaseManager = Depends(get_database_manager) ): """ Получение информации о пользователе. """ try: print(f"Получение пользователя с telegram_id: {telegram_id}") user = await db_manager.get_user_by_telegram_id(telegram_id) if not user: logger.warning(f"Пользователь с telegram_id {telegram_id} не найден.") raise HTTPException(status_code=404, detail="User not found") print(f"Пользователь найден: ID={user.telegram_id}, Username={user.username}") user_response = UserResponse( telegram_id=user.telegram_id, username=user.username, balance=user.balance, invited_by=user.invited_by if user.invited_by is not None else None, created_at=user.created_at.isoformat(), updated_at=user.updated_at.isoformat() ) return user_response except HTTPException as http_ex: # Позволяет обработать HTTPException отдельно raise http_ex except SQLAlchemyError as e: logger.error(f"Ошибка базы данных при получении пользователя с telegram_id {telegram_id}: {e}") raise HTTPException(status_code=500, detail="Database error") except Exception as e: logger.exception(f"Неожиданная ошибка при получении пользователя с telegram_id {telegram_id}: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.get("/user/{telegram_id}/transactions", summary="Последние транзакции пользователя") async def last_transactions( telegram_id: int, db_manager: DatabaseManager = Depends(get_database_manager) ): """ Возвращает список последних транзакций пользователя. """ logger.info(f"Получен запрос на транзакции для пользователя: {telegram_id}") try: logger.debug(f"Вызов метода get_transaction с user_id={telegram_id}") transactions = await db_manager.get_transaction(telegram_id) if transactions == "ERROR": logger.error(f"Ошибка при получении транзакций для пользователя: {telegram_id}") raise HTTPException(status_code=500, detail="Failed to fetch transactions") if transactions == None: response = [] logger.info(f"Формирование ответа для пользователя {telegram_id}: {response}") return response logger.debug(f"Транзакции для {telegram_id}: {transactions}") response = [] for tx in transactions: # Проверяем, что транзакция существует и имеет created_at if tx is None: continue if tx.status.value == "pending": continue # Обрабатываем created_at (может быть None) created_at_str = None if tx.created_at: created_at_str = tx.created_at.isoformat() else: created_at_str = datetime.utcnow().isoformat() # или любое значение по умолчанию response.append({ "id": tx.id, "amount": float(tx.amount) if tx.amount else 0.0, "created_at": created_at_str, "type": tx.type.value if hasattr(tx.type, 'value') else str(tx.type), }) logger.info(f"Формирование ответа для пользователя {telegram_id}: {response}") return response except HTTPException as http_ex: logger.warning(f"HTTP ошибка для {telegram_id}: {http_ex.detail}") raise http_ex except SQLAlchemyError as db_ex: logger.error(f"Ошибка базы данных для {telegram_id}: {db_ex}") raise HTTPException(status_code=500, detail="Database error") except Exception as e: logger.exception(f"Неожиданная ошибка для {telegram_id}: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.post("/user/{referrer_id}/add_referral", summary="Обновить баланс") async def add_referal( referrer_id: int, request: AddReferal, db_manager: DatabaseManager = Depends(get_database_manager) ): """ Обновляет баланс пользователя. """ logger.info(f"Получен запрос на добавление реферала: telegram_id={referrer_id}") try: result = await db_manager.add_referal(referrer_id,request.invited_id) if result == "ERROR": logger.error(f"Ошибка добавления реферала для {referrer_id} c айди {request.invited_id}") raise HTTPException(status_code=500, detail="Failed to update balance") logger.info(f"Добавлен реферал для {referrer_id} c айди {request.invited_id}") return {"message": "Balance updated successfully"} except HTTPException as http_ex: logger.warning(f"HTTP ошибка: {http_ex.detail}") raise http_ex except SQLAlchemyError as db_ex: logger.error(f"Ошибка базы данных при добавлении рефералу {referrer_id}: {db_ex}") raise HTTPException(status_code=500, detail="Database error") except Exception as e: logger.exception(f"Неожиданная ошибка при добавлении рефералу {referrer_id}: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.get("/user/{telegram_id}/referrals", summary="Получить колво рефералов") async def get_referral_count( telegram_id: int, db_manager: DatabaseManager = Depends(get_database_manager) ): try: result = await db_manager.get_referrals_count(telegram_id) if result == "ERROR": logger.error(f"Ошибка получения рефералов для пользователя: {telegram_id}") raise HTTPException(status_code=500, detail="Failed to get referrals") logger.info(f"Количество приглашённых {result}") return {"invited_count": result} except HTTPException as http_ex: logger.warning(f"HTTP ошибка: {http_ex.detail}") raise http_ex except SQLAlchemyError as db_ex: logger.error(f"Ошибка базы данных при получении рефералов пользователя {telegram_id}: {db_ex}") raise HTTPException(status_code=500, detail="Database error") except Exception as e: logger.exception(f"Неожиданная ошибка при получении рефералов {telegram_id}: {e}") raise HTTPException(status_code=500, detail=str(e))