diff --git a/main.py b/main.py index 1e98dd5..a41de6b 100644 --- a/main.py +++ b/main.py @@ -202,6 +202,9 @@ async def get_current_tg_agent(request: Request, db: Session = Depends(get_db)): @app.post("/register", tags=["partner-tg"], response_model=RegisterResponse) def register(req: RegisterRequest, db: Session = Depends(get_db)): + """ + Регистрирует нового Telegram-агента в системе. + """ tg_id = req.tg_id chat_id = req.chat_id phone = req.phone @@ -258,11 +261,14 @@ def create_access_token(data: dict, expires_delta: timedelta = None): @app.post("/token", response_model=Token, tags=["bff", "token"]) def login_account_for_access_token( - # login: str = Body(...), - # password: str = Body(...), form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db) ): + """ + Авторизует аккаунт и возвращает токен доступа. + """ + # login: str = Body(...), + # password: str = Body(...), account = get_account_by_login(db, form_data.username) if not account or not verify_password(form_data.password, account.password_hash): raise HTTPException( @@ -280,11 +286,17 @@ def login_account_for_access_token( @app.get("/ref", response_model=List[RefResponse], tags=["partner-tg"]) def get_refs(current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Session = Depends(get_db)): + """ + Возвращает список реферальных ссылок текущего Telegram-агента. + """ refs = db.exec(select(Ref).where(Ref.tg_agent_id == current_tg_agent.id)).all() return [RefResponse(ref=r.ref, description=r.description or "") for r in refs] @app.post("/ref/add", tags=["partner-tg"], response_model=RefAddResponse) def add_ref(req: RefAddRequest, current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Session = Depends(get_db)): + """ + Добавляет новую реферальную ссылку для текущего Telegram-агента. + """ new_ref = Ref( tg_agent_id=current_tg_agent.id, ref=str(uuid4()), @@ -297,6 +309,9 @@ def add_ref(req: RefAddRequest, current_tg_agent: TgAgent = Depends(get_current_ @app.get("/ref/stat", tags=["partner-tg"], response_model=RefStatResponse) def get_ref_stat(current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Session = Depends(get_db)): + """ + Возвращает статистику по реферальным ссылкам текущего Telegram-агента. + """ # 1. Получаем все реферальные ссылки пользователя refs = db.exec(select(Ref).where(Ref.tg_agent_id == current_tg_agent.id)).all() result = [] @@ -314,6 +329,9 @@ def get_ref_stat(current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: @app.get("/stat", tags=["partner-tg"], response_model=StatResponse) def get_stat(current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Session = Depends(get_db)): + """ + Возвращает общую статистику для текущего Telegram-агента. + """ # 1. Получаем все реферальные ссылки пользователя refs = db.exec(select(Ref).where(Ref.tg_agent_id == current_tg_agent.id)).all() ref_ids = [r.id for r in refs] @@ -333,6 +351,9 @@ def get_stat(current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Sess @app.get("/dashboard/cards", tags=["bff", "dashboard"], response_model=DashboardCardsResponse) def get_dashboard_cards(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)): + """ + Возвращает данные для карточек на главной панели (dashboard) пользователя, включая общий доход, выплаты, активных рефералов, ожидающие выплаты и общее количество продаж. + """ # 1. Общий доход - сумма всех Sale.cost total_revenue = db.exec(select(Sale).where(Sale.company_id == current_account.company_id)).all() totalRevenue = sum(sale.cost for sale in total_revenue) @@ -361,6 +382,9 @@ def get_dashboard_cards(current_account: Account = Depends(get_current_account), @app.get("/dashboard/chart/total", tags=["bff", "dashboard"], response_model=DashboardChartTotalResponse) def get_dashboard_chart_total(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)): + """ + Возвращает данные для графика "Общий доход и продажи по датам" на главной панели (dashboard). + """ # Группируем продажи по дате (день) result = db.exec( select( @@ -379,6 +403,9 @@ def get_dashboard_chart_total(current_account: Account = Depends(get_current_acc @app.get("/dashboard/chart/agent", tags=["bff", "dashboard"], response_model=DashboardChartAgentResponse) def get_dashboard_chart_agent(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)): + """ + Возвращает данные для графика "Продажи по агентам" на главной панели (dashboard). + """ # Получаем всех агентов agents = db.exec(select(TgAgent).where(TgAgent.company_id == current_account.company_id)).all() result = [] @@ -411,6 +438,10 @@ def get_agents_stat( date_end: str = Query(None), current_account: Account = Depends(get_current_account), ): + """ + Возвращает статистику по агентам компании, включая количество рефералов, продаж, сумму продаж и начислений. + Возможна фильтрация по дате создания агентов. + """ agents_query = select(TgAgent).where(TgAgent.company_id == current_account.company_id) if date_start: agents_query = agents_query.where(TgAgent.create_dttm >= date_start) @@ -451,6 +482,10 @@ def get_referrals_stat( date_end: str = Query(None), current_account: Account = Depends(get_current_account), ): + """ + Возвращает статистику по реферальным ссылкам компании, включая имя агента, описание, сумму и количество продаж. + Возможна фильтрация по дате создания рефералов. + """ refs_query = select(Ref).join(TgAgent).where(TgAgent.company_id == current_account.company_id) if date_start: refs_query = refs_query.where(Ref.create_dttm >= date_start) @@ -479,6 +514,10 @@ def get_sales_stat( date_end: str = Query(None), current_account: Account = Depends(get_current_account), ): + """ + Возвращает статистику по продажам компании, включая ID продажи, стоимость, начисления, реферала и имя агента. + Возможна фильтрация по дате создания продаж. + """ sales_query = select(Sale).where(Sale.company_id == current_account.company_id) if date_start: sales_query = sales_query.where(Sale.create_dttm >= date_start) @@ -506,6 +545,9 @@ def get_sales_stat( @app.get("/billing/cards", tags=["bff", "billing"], response_model=BillingCardsResponse) def get_billing_cards(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)): + """ + Возвращает ключевые показатели биллинга для компании, включая общий заработок, общие выплаты и доступные к выводу средства. + """ # 1. cost - Общий заработок (сумма всех Sale.cost) sales = db.exec(select(Sale).where(Sale.company_id == current_account.company_id)).all() cost = sum(sale.cost for sale in sales) @@ -531,6 +573,10 @@ def get_billing_payouts_transactions( date_end: str = Query(None), current_account: Account = Depends(get_current_account), ): + """ + Возвращает список транзакций выплат для компании текущего пользователя. + Возможна фильтрация по дате создания. + """ # Используем AgentTransaction вместо Transaction # Явно выбираем обе модели для корректной распаковки query = select(AgentTransaction, TgAgent).join(TgAgent).where(TgAgent.company_id == current_account.company_id) @@ -562,6 +608,9 @@ def get_billing_payouts_transactions( @app.get("/billing/chart/stat", tags=["bff", "billing"], response_model=BillingChartStatResponse) def get_billing_chart_stat(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)): + """ + Возвращает статистику выплат по датам и статусам для компании текущего пользователя. + """ # Группируем агентские транзакции по дате (день) и статусу result = db.exec( select( @@ -584,6 +633,9 @@ def get_billing_chart_stat(current_account: Account = Depends(get_current_accoun @app.get("/billing/chart/pie", tags=["bff", "billing"], response_model=BillingChartPieResponse) def get_billing_chart_pie(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)): + """ + Возвращает круговую диаграмму статистики выплат по статусам для компании текущего пользователя. + """ # Группируем агентские транзакции по статусу result = db.exec( select( @@ -601,6 +653,9 @@ def get_billing_chart_pie(current_account: Account = Depends(get_current_account @app.post("/tg_auth", tags=["partner-tg"], response_model=TgAuthResponse) def tg_auth(hash: str = Body(..., embed=True), db: Session = Depends(get_db)): + """ + Авторизует Telegram-агента по хешу. + """ tg_agent = db.exec(select(TgAgent).where(TgAgent.hash == hash)).first() if not tg_agent: raise HTTPException(status_code=401, detail="Hash not found") @@ -620,6 +675,9 @@ def get_account_by_login(db: Session, login: str) -> Optional[Account]: @app.get("/account", tags=["bff", "account"], response_model=AccountResponse) def get_account(current_account: Account = Depends(get_current_account)): + """ + Возвращает базовую информацию об аккаунте текущего пользователя (имя и фамилию). + """ return { "firstName": current_account.firstName, "surname": current_account.surname @@ -627,6 +685,9 @@ def get_account(current_account: Account = Depends(get_current_account)): @app.get("/account/profile", tags=["bff", "account"], response_model=AccountProfileResponse) def get_account_profile(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)): + """ + Возвращает полную информацию о профиле аккаунта текущего пользователя, включая данные компании. + """ company = db.exec(select(Company).where(Company.id == current_account.company_id)).first() if not company: raise HTTPException(status_code=404, detail="Компания не найдена") @@ -649,6 +710,9 @@ def update_account_profile( current_account: Account = Depends(get_current_account), db: Session = Depends(get_db) ): + """ + Обновляет информацию профиля текущего пользователя. + """ # Проверка, что все поля заполнены (Pydantic уже валидирует email и обязательность) if not req.firstName.strip() or not req.surname.strip() or not req.email or not req.phone.strip(): raise HTTPException(status_code=400, detail="Все поля должны быть заполнены") @@ -668,6 +732,9 @@ def change_account_password( current_account: Account = Depends(get_current_account), db: Session = Depends(get_db) ): + """ + Изменяет пароль текущего пользователя. + """ # Проверяем текущий пароль if not verify_password(req.currentPassword, current_account.password_hash): raise HTTPException(status_code=400, detail="Текущий пароль неверный") @@ -759,7 +826,7 @@ def update_auto_approve_settings( db: Session = Depends(get_db) ): """ - Обновляет настройку автоматического подтверждения для компании пользователя. + Обновляет настройку автоматического подтверждения транзакций для компании пользователя. При необходимости переводит транзакции из 'waiting' в 'new'. """ company = db.exec(select(Company).where(Company.id == current_account.company_id)).first()