Compare commits
3 Commits
5d14969f82
...
899d7040b4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
899d7040b4 | ||
|
|
bab15debe4 | ||
|
|
6b8b4ac059 |
171
bff_models.py
Normal file
171
bff_models.py
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
from pydantic import BaseModel, Field, EmailStr
|
||||||
|
from typing import Optional, List
|
||||||
|
from datetime import datetime
|
||||||
|
import uuid
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
# BFF Models
|
||||||
|
class Token(BaseModel):
|
||||||
|
access_token: str
|
||||||
|
token_type: str
|
||||||
|
|
||||||
|
class AccountProfileUpdateRequest(BaseModel):
|
||||||
|
firstName: str
|
||||||
|
surname: str
|
||||||
|
email: EmailStr
|
||||||
|
phone: str
|
||||||
|
|
||||||
|
class AccountPasswordChangeRequest(BaseModel):
|
||||||
|
currentPassword: str
|
||||||
|
newPassword: str
|
||||||
|
|
||||||
|
class TransactionStatus(str, Enum):
|
||||||
|
WAITING = 'waiting'
|
||||||
|
PROCESS = 'process'
|
||||||
|
DONE = 'done'
|
||||||
|
REJECT = 'reject'
|
||||||
|
ERROR = 'error'
|
||||||
|
NEW = 'new'
|
||||||
|
|
||||||
|
class AgentTransactionResponse(BaseModel):
|
||||||
|
amount: float
|
||||||
|
status: TransactionStatus
|
||||||
|
transaction_group: uuid.UUID
|
||||||
|
create_dttm: datetime
|
||||||
|
update_dttm: datetime
|
||||||
|
agent_name: Optional[str] = None
|
||||||
|
|
||||||
|
class AutoApproveSettingsRequest(BaseModel):
|
||||||
|
auto_approve: bool
|
||||||
|
apply_to_current: Optional[bool] = False
|
||||||
|
|
||||||
|
class ApproveTransactionsRequest(BaseModel):
|
||||||
|
transaction_ids: List[uuid.UUID]
|
||||||
|
|
||||||
|
# New Response Models for BFF APIs
|
||||||
|
|
||||||
|
class RegisterResponse(BaseModel):
|
||||||
|
msg: str
|
||||||
|
|
||||||
|
class TgAuthResponse(BaseModel):
|
||||||
|
msg: str
|
||||||
|
tg_id: int
|
||||||
|
|
||||||
|
class DashboardCardsResponse(BaseModel):
|
||||||
|
totalRevenue: float
|
||||||
|
totalPayouts: float
|
||||||
|
activeReferrals: int
|
||||||
|
pendingPayouts: float
|
||||||
|
totalSales: int
|
||||||
|
|
||||||
|
class DashboardChartTotalItem(BaseModel):
|
||||||
|
date: str
|
||||||
|
revenue: float
|
||||||
|
sales: int
|
||||||
|
|
||||||
|
class DashboardChartTotalResponse(BaseModel):
|
||||||
|
items: List[DashboardChartTotalItem]
|
||||||
|
|
||||||
|
class DashboardChartAgentItem(BaseModel):
|
||||||
|
name: str
|
||||||
|
count: int
|
||||||
|
sum: float
|
||||||
|
|
||||||
|
class DashboardChartAgentResponse(BaseModel):
|
||||||
|
items: List[DashboardChartAgentItem]
|
||||||
|
|
||||||
|
class StatAgentsItem(BaseModel):
|
||||||
|
name: str
|
||||||
|
refCount: int
|
||||||
|
salesCount: int
|
||||||
|
salesSum: float
|
||||||
|
crediting: float
|
||||||
|
|
||||||
|
class StatAgentsResponse(BaseModel):
|
||||||
|
items: List[StatAgentsItem]
|
||||||
|
|
||||||
|
class StatReferralsItem(BaseModel):
|
||||||
|
ref: str
|
||||||
|
agent: Optional[str] = None
|
||||||
|
description: str
|
||||||
|
salesSum: float
|
||||||
|
salesCount: int
|
||||||
|
|
||||||
|
class StatReferralsResponse(BaseModel):
|
||||||
|
items: List[StatReferralsItem]
|
||||||
|
|
||||||
|
class StatSalesItem(BaseModel):
|
||||||
|
saleId: str
|
||||||
|
cost: float
|
||||||
|
crediting: float
|
||||||
|
ref: Optional[str] = None
|
||||||
|
name: Optional[str] = None
|
||||||
|
|
||||||
|
class StatSalesResponse(BaseModel):
|
||||||
|
items: List[StatSalesItem]
|
||||||
|
|
||||||
|
class BillingCardsResponse(BaseModel):
|
||||||
|
cost: float
|
||||||
|
crediting: float
|
||||||
|
pendingPayouts: float
|
||||||
|
|
||||||
|
class BillingChartStatItem(BaseModel):
|
||||||
|
date: str
|
||||||
|
status: str
|
||||||
|
count: int
|
||||||
|
|
||||||
|
class BillingChartStatResponse(BaseModel):
|
||||||
|
items: List[BillingChartStatItem]
|
||||||
|
|
||||||
|
class BillingChartPieItem(BaseModel):
|
||||||
|
status: str
|
||||||
|
count: int
|
||||||
|
|
||||||
|
class BillingChartPieResponse(BaseModel):
|
||||||
|
items: List[BillingChartPieItem]
|
||||||
|
|
||||||
|
class BillingPayoutsTransactionsItem(BaseModel):
|
||||||
|
id: uuid.UUID
|
||||||
|
amount: float
|
||||||
|
agent: Optional[str] = None
|
||||||
|
status: TransactionStatus
|
||||||
|
create_dttm: datetime
|
||||||
|
update_dttm: datetime
|
||||||
|
|
||||||
|
class BillingPayoutsTransactionsResponse(BaseModel):
|
||||||
|
items: List[BillingPayoutsTransactionsItem]
|
||||||
|
|
||||||
|
class AccountResponse(BaseModel):
|
||||||
|
firstName: Optional[str] = None
|
||||||
|
surname: Optional[str] = None
|
||||||
|
|
||||||
|
class CompanyProfileResponse(BaseModel):
|
||||||
|
name: str
|
||||||
|
key: str
|
||||||
|
commission: float
|
||||||
|
|
||||||
|
class AccountProfileResponse(BaseModel):
|
||||||
|
firstName: Optional[str] = None
|
||||||
|
surname: Optional[str] = None
|
||||||
|
phone: Optional[str] = None
|
||||||
|
email: Optional[EmailStr] = None
|
||||||
|
create_dttm: datetime
|
||||||
|
company: CompanyProfileResponse
|
||||||
|
|
||||||
|
class AccountProfileUpdateResponse(BaseModel):
|
||||||
|
msg: str
|
||||||
|
|
||||||
|
class AccountPasswordChangeResponse(BaseModel):
|
||||||
|
msg: str
|
||||||
|
|
||||||
|
class AutoApproveSettingsGetResponse(BaseModel):
|
||||||
|
auto_approve_transactions: bool
|
||||||
|
|
||||||
|
class AutoApproveSettingsUpdateResponse(BaseModel):
|
||||||
|
msg: str
|
||||||
|
auto_approve_transactions: bool
|
||||||
|
|
||||||
|
class ApproveTransactionsResult(BaseModel):
|
||||||
|
msg: str
|
||||||
|
approved_count: int
|
||||||
108
main.py
108
main.py
@ -5,7 +5,8 @@ from sqlmodel import SQLModel, Field, create_engine, Session, select
|
|||||||
from passlib.context import CryptContext
|
from passlib.context import CryptContext
|
||||||
from typing import Optional, List, Dict
|
from typing import Optional, List, Dict
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from models import RefAddRequest, RefResponse, RegisterRequest, Token, TokenRequest
|
from bff_models import Token, AccountProfileUpdateRequest, AccountPasswordChangeRequest, AgentTransactionResponse, AutoApproveSettingsRequest, ApproveTransactionsRequest, TransactionStatus, RegisterResponse, DashboardCardsResponse, DashboardChartTotalResponse, DashboardChartAgentResponse, StatAgentsResponse, StatReferralsResponse, StatSalesResponse, BillingCardsResponse, BillingChartStatResponse, BillingChartPieResponse, AccountResponse, CompanyProfileResponse, AccountProfileResponse, AccountProfileUpdateResponse, AccountPasswordChangeResponse, AutoApproveSettingsGetResponse, AutoApproveSettingsUpdateResponse, ApproveTransactionsResult, TgAuthResponse, BillingPayoutsTransactionsResponse
|
||||||
|
from tg_models import RefAddRequest, RefResponse, RegisterRequest, TokenRequest, RefAddResponse, RefStatResponse, StatResponse
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
@ -199,7 +200,7 @@ async def get_current_tg_agent(request: Request, db: Session = Depends(get_db)):
|
|||||||
# Регистрация
|
# Регистрация
|
||||||
|
|
||||||
|
|
||||||
@app.post("/register", tags=["partner-tg"])
|
@app.post("/register", tags=["partner-tg"], response_model=RegisterResponse)
|
||||||
def register(req: RegisterRequest, db: Session = Depends(get_db)):
|
def register(req: RegisterRequest, db: Session = Depends(get_db)):
|
||||||
tg_id = req.tg_id
|
tg_id = req.tg_id
|
||||||
chat_id = req.chat_id
|
chat_id = req.chat_id
|
||||||
@ -255,7 +256,7 @@ def create_access_token(data: dict, expires_delta: timedelta = None):
|
|||||||
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
||||||
return encoded_jwt
|
return encoded_jwt
|
||||||
|
|
||||||
@app.post("/token", response_model=Token, tags=["bff"])
|
@app.post("/token", response_model=Token, tags=["bff", "token"])
|
||||||
def login_account_for_access_token(
|
def login_account_for_access_token(
|
||||||
# login: str = Body(...),
|
# login: str = Body(...),
|
||||||
# password: str = Body(...),
|
# password: str = Body(...),
|
||||||
@ -277,12 +278,12 @@ def login_account_for_access_token(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/ref", response_model=list[RefResponse], tags=["partner-tg"])
|
@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)):
|
def get_refs(current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Session = Depends(get_db)):
|
||||||
refs = db.exec(select(Ref).where(Ref.tg_agent_id == current_tg_agent.id)).all()
|
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]
|
return [RefResponse(ref=r.ref, description=r.description or "") for r in refs]
|
||||||
|
|
||||||
@app.post("/ref/add", tags=["partner-tg"])
|
@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)):
|
def add_ref(req: RefAddRequest, current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Session = Depends(get_db)):
|
||||||
new_ref = Ref(
|
new_ref = Ref(
|
||||||
tg_agent_id=current_tg_agent.id,
|
tg_agent_id=current_tg_agent.id,
|
||||||
@ -294,7 +295,7 @@ def add_ref(req: RefAddRequest, current_tg_agent: TgAgent = Depends(get_current_
|
|||||||
db.refresh(new_ref)
|
db.refresh(new_ref)
|
||||||
return {"ref": new_ref.ref}
|
return {"ref": new_ref.ref}
|
||||||
|
|
||||||
@app.get("/ref/stat", tags=["partner-tg"])
|
@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)):
|
def get_ref_stat(current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Session = Depends(get_db)):
|
||||||
# 1. Получаем все реферальные ссылки пользователя
|
# 1. Получаем все реферальные ссылки пользователя
|
||||||
refs = db.exec(select(Ref).where(Ref.tg_agent_id == current_tg_agent.id)).all()
|
refs = db.exec(select(Ref).where(Ref.tg_agent_id == current_tg_agent.id)).all()
|
||||||
@ -311,7 +312,7 @@ def get_ref_stat(current_tg_agent: TgAgent = Depends(get_current_tg_agent), db:
|
|||||||
})
|
})
|
||||||
return {"refData": result}
|
return {"refData": result}
|
||||||
|
|
||||||
@app.get("/stat", tags=["partner-tg"])
|
@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)):
|
def get_stat(current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Session = Depends(get_db)):
|
||||||
# 1. Получаем все реферальные ссылки пользователя
|
# 1. Получаем все реферальные ссылки пользователя
|
||||||
refs = db.exec(select(Ref).where(Ref.tg_agent_id == current_tg_agent.id)).all()
|
refs = db.exec(select(Ref).where(Ref.tg_agent_id == current_tg_agent.id)).all()
|
||||||
@ -330,21 +331,21 @@ def get_stat(current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Sess
|
|||||||
"availableWithdrawal": availableWithdrawal
|
"availableWithdrawal": availableWithdrawal
|
||||||
}
|
}
|
||||||
|
|
||||||
@app.get("/dashboard/cards", tags=["bff"])
|
@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)):
|
def get_dashboard_cards(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)):
|
||||||
# 1. Общий доход - сумма всех Sale.cost
|
# 1. Общий доход - сумма всех Sale.cost
|
||||||
total_revenue = db.exec(select(Sale)).all()
|
total_revenue = db.exec(select(Sale).where(Sale.company_id == current_account.company_id)).all()
|
||||||
totalRevenue = sum(sale.cost for sale in total_revenue)
|
totalRevenue = sum(sale.cost for sale in total_revenue)
|
||||||
|
|
||||||
# 2. Общие выплаты - сумма всех Sale.crediting
|
# 2. Общие выплаты - сумма всех Sale.crediting
|
||||||
totalPayouts = sum(sale.crediting for sale in total_revenue)
|
totalPayouts = sum(sale.crediting for sale in total_revenue)
|
||||||
|
|
||||||
# 3. Активные рефералы - количество уникальных TgAgent.tg_id
|
# 3. Активные рефералы - количество уникальных TgAgent.tg_id
|
||||||
unique_agents = db.exec(select(TgAgent.tg_id)).all()
|
unique_agents = db.exec(select(TgAgent.tg_id).where(TgAgent.company_id == current_account.company_id)).all()
|
||||||
activeReferrals = len(set(unique_agents))
|
activeReferrals = len(set(unique_agents))
|
||||||
|
|
||||||
# 4. Ожидающие выплаты - сумма AgentTransaction со статусом 'waiting'
|
# 4. Ожидающие выплаты - сумма AgentTransaction со статусом 'waiting'
|
||||||
pending_agent_transactions = db.exec(select(AgentTransaction).where(AgentTransaction.status == 'waiting')).all()
|
pending_agent_transactions = db.exec(select(AgentTransaction).join(TgAgent).where(TgAgent.company_id == current_account.company_id).where(AgentTransaction.status == 'waiting')).all()
|
||||||
pendingPayouts = sum(t.amount for t in pending_agent_transactions)
|
pendingPayouts = sum(t.amount for t in pending_agent_transactions)
|
||||||
|
|
||||||
# 5. Количество продаж
|
# 5. Количество продаж
|
||||||
@ -358,7 +359,7 @@ def get_dashboard_cards(current_account: Account = Depends(get_current_account),
|
|||||||
"totalSales": totalSales
|
"totalSales": totalSales
|
||||||
}
|
}
|
||||||
|
|
||||||
@app.get("/dashboard/chart/total", tags=["bff"])
|
@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)):
|
def get_dashboard_chart_total(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)):
|
||||||
# Группируем продажи по дате (день)
|
# Группируем продажи по дате (день)
|
||||||
result = db.exec(
|
result = db.exec(
|
||||||
@ -366,7 +367,7 @@ def get_dashboard_chart_total(current_account: Account = Depends(get_current_acc
|
|||||||
func.strftime('%Y-%m-%d', Sale.create_dttm).label('date'),
|
func.strftime('%Y-%m-%d', Sale.create_dttm).label('date'),
|
||||||
func.sum(Sale.cost).label('revenue'),
|
func.sum(Sale.cost).label('revenue'),
|
||||||
func.count(Sale.id).label('sales')
|
func.count(Sale.id).label('sales')
|
||||||
).group_by(func.strftime('%Y-%m-%d', Sale.create_dttm))
|
).where(Sale.company_id == current_account.company_id).group_by(func.strftime('%Y-%m-%d', Sale.create_dttm))
|
||||||
.order_by(func.strftime('%Y-%m-%d', Sale.create_dttm))
|
.order_by(func.strftime('%Y-%m-%d', Sale.create_dttm))
|
||||||
).all()
|
).all()
|
||||||
# Преобразуем результат в нужный формат
|
# Преобразуем результат в нужный формат
|
||||||
@ -374,12 +375,12 @@ def get_dashboard_chart_total(current_account: Account = Depends(get_current_acc
|
|||||||
{"date": row.date, "revenue": row.revenue or 0, "sales": row.sales or 0}
|
{"date": row.date, "revenue": row.revenue or 0, "sales": row.sales or 0}
|
||||||
for row in result
|
for row in result
|
||||||
]
|
]
|
||||||
return JSONResponse(content=data)
|
return DashboardChartTotalResponse(items=data)
|
||||||
|
|
||||||
@app.get("/dashboard/chart/agent", tags=["bff"])
|
@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)):
|
def get_dashboard_chart_agent(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)):
|
||||||
# Получаем всех агентов
|
# Получаем всех агентов
|
||||||
agents = db.exec(select(TgAgent)).all()
|
agents = db.exec(select(TgAgent).where(TgAgent.company_id == current_account.company_id)).all()
|
||||||
result = []
|
result = []
|
||||||
for agent in agents:
|
for agent in agents:
|
||||||
# Получаем все рефы этого агента
|
# Получаем все рефы этого агента
|
||||||
@ -401,16 +402,16 @@ def get_dashboard_chart_agent(current_account: Account = Depends(get_current_acc
|
|||||||
"count": sales_count,
|
"count": sales_count,
|
||||||
"sum": sales_sum
|
"sum": sales_sum
|
||||||
})
|
})
|
||||||
return JSONResponse(content=result)
|
return DashboardChartAgentResponse(items=result)
|
||||||
|
|
||||||
@app.get("/stat/agents", tags=["bff"])
|
@app.get("/stat/agents", tags=["bff", "stat"], response_model=StatAgentsResponse)
|
||||||
def get_agents_stat(
|
def get_agents_stat(
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
date_start: str = Query(None),
|
date_start: str = Query(None),
|
||||||
date_end: str = Query(None),
|
date_end: str = Query(None),
|
||||||
current_account: Account = Depends(get_current_account),
|
current_account: Account = Depends(get_current_account),
|
||||||
):
|
):
|
||||||
agents_query = select(TgAgent)
|
agents_query = select(TgAgent).where(TgAgent.company_id == current_account.company_id)
|
||||||
if date_start:
|
if date_start:
|
||||||
agents_query = agents_query.where(TgAgent.create_dttm >= date_start)
|
agents_query = agents_query.where(TgAgent.create_dttm >= date_start)
|
||||||
if date_end:
|
if date_end:
|
||||||
@ -441,16 +442,16 @@ def get_agents_stat(
|
|||||||
"salesSum": sales_sum,
|
"salesSum": sales_sum,
|
||||||
"crediting": crediting_sum
|
"crediting": crediting_sum
|
||||||
})
|
})
|
||||||
return JSONResponse(content=result)
|
return StatAgentsResponse(items=result)
|
||||||
|
|
||||||
@app.get("/stat/referrals", tags=["bff"])
|
@app.get("/stat/referrals", tags=["bff", "stat"], response_model=StatReferralsResponse)
|
||||||
def get_referrals_stat(
|
def get_referrals_stat(
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
date_start: str = Query(None),
|
date_start: str = Query(None),
|
||||||
date_end: str = Query(None),
|
date_end: str = Query(None),
|
||||||
current_account: Account = Depends(get_current_account),
|
current_account: Account = Depends(get_current_account),
|
||||||
):
|
):
|
||||||
refs_query = select(Ref)
|
refs_query = select(Ref).join(TgAgent).where(TgAgent.company_id == current_account.company_id)
|
||||||
if date_start:
|
if date_start:
|
||||||
refs_query = refs_query.where(Ref.create_dttm >= date_start)
|
refs_query = refs_query.where(Ref.create_dttm >= date_start)
|
||||||
if date_end:
|
if date_end:
|
||||||
@ -469,16 +470,16 @@ def get_referrals_stat(
|
|||||||
"salesSum": sales_sum,
|
"salesSum": sales_sum,
|
||||||
"salesCount": sales_count
|
"salesCount": sales_count
|
||||||
})
|
})
|
||||||
return JSONResponse(content=result)
|
return StatReferralsResponse(items=result)
|
||||||
|
|
||||||
@app.get("/stat/sales", tags=["bff"])
|
@app.get("/stat/sales", tags=["bff", "stat"], response_model=StatSalesResponse)
|
||||||
def get_sales_stat(
|
def get_sales_stat(
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
date_start: str = Query(None),
|
date_start: str = Query(None),
|
||||||
date_end: str = Query(None),
|
date_end: str = Query(None),
|
||||||
current_account: Account = Depends(get_current_account),
|
current_account: Account = Depends(get_current_account),
|
||||||
):
|
):
|
||||||
sales_query = select(Sale)
|
sales_query = select(Sale).where(Sale.company_id == current_account.company_id)
|
||||||
if date_start:
|
if date_start:
|
||||||
sales_query = sales_query.where(Sale.create_dttm >= date_start)
|
sales_query = sales_query.where(Sale.create_dttm >= date_start)
|
||||||
if date_end:
|
if date_end:
|
||||||
@ -501,20 +502,20 @@ def get_sales_stat(
|
|||||||
"ref": ref_obj.ref if ref_obj else None,
|
"ref": ref_obj.ref if ref_obj else None,
|
||||||
"name": agent_obj.name if agent_obj else None
|
"name": agent_obj.name if agent_obj else None
|
||||||
})
|
})
|
||||||
return JSONResponse(content=result)
|
return StatSalesResponse(items=result)
|
||||||
|
|
||||||
@app.get("/billing/cards", tags=["bff"])
|
@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)):
|
def get_billing_cards(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)):
|
||||||
# 1. cost - Общий заработок (сумма всех Sale.cost)
|
# 1. cost - Общий заработок (сумма всех Sale.cost)
|
||||||
sales = db.exec(select(Sale)).all()
|
sales = db.exec(select(Sale).where(Sale.company_id == current_account.company_id)).all()
|
||||||
cost = sum(sale.cost for sale in sales)
|
cost = sum(sale.cost for sale in sales)
|
||||||
|
|
||||||
# 2. crediting - Общие выплаты (сумма PartnerTransaction типа 'agent_payout' со статусом 'done')
|
# 2. crediting - Общие выплаты (сумма PartnerTransaction типа 'agent_payout' со статусом 'done')
|
||||||
completed_payouts = db.exec(select(PartnerTransaction).where(PartnerTransaction.type == 'agent_payout').where(PartnerTransaction.status == 'done')).all()
|
completed_payouts = db.exec(select(PartnerTransaction).where(PartnerTransaction.type == 'agent_payout').where(PartnerTransaction.status == 'done').where(PartnerTransaction.company_id == current_account.company_id)).all()
|
||||||
crediting = sum(t.amount for t in completed_payouts)
|
crediting = sum(t.amount for t in completed_payouts)
|
||||||
|
|
||||||
# 3. pendingPayouts - Доступно к выводу всеми партнерами (сумма всех доступных балансов агентов)
|
# 3. pendingPayouts - Доступно к выводу всеми партнерами (сумма всех доступных балансов агентов)
|
||||||
agent_balances = db.exec(select(AgentBalance)).all()
|
agent_balances = db.exec(select(AgentBalance).join(TgAgent).where(TgAgent.company_id == current_account.company_id)).all()
|
||||||
pendingPayouts = sum(balance.available_balance for balance in agent_balances)
|
pendingPayouts = sum(balance.available_balance for balance in agent_balances)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -523,7 +524,7 @@ def get_billing_cards(current_account: Account = Depends(get_current_account), d
|
|||||||
"pendingPayouts": pendingPayouts
|
"pendingPayouts": pendingPayouts
|
||||||
}
|
}
|
||||||
|
|
||||||
@app.get("/billing/payouts/transactions", tags=["bff"])
|
@app.get("/billing/payouts/transactions", tags=["bff", "billing"], response_model=BillingPayoutsTransactionsResponse)
|
||||||
def get_billing_payouts_transactions(
|
def get_billing_payouts_transactions(
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
date_start: str = Query(None),
|
date_start: str = Query(None),
|
||||||
@ -532,7 +533,7 @@ def get_billing_payouts_transactions(
|
|||||||
):
|
):
|
||||||
# Используем AgentTransaction вместо Transaction
|
# Используем AgentTransaction вместо Transaction
|
||||||
# Явно выбираем обе модели для корректной распаковки
|
# Явно выбираем обе модели для корректной распаковки
|
||||||
query = select(AgentTransaction, TgAgent).join(TgAgent)
|
query = select(AgentTransaction, TgAgent).join(TgAgent).where(TgAgent.company_id == current_account.company_id)
|
||||||
if date_start:
|
if date_start:
|
||||||
query = query.where(AgentTransaction.create_dttm >= date_start)
|
query = query.where(AgentTransaction.create_dttm >= date_start)
|
||||||
if date_end:
|
if date_end:
|
||||||
@ -544,17 +545,22 @@ def get_billing_payouts_transactions(
|
|||||||
results = db.exec(query).all()
|
results = db.exec(query).all()
|
||||||
result = []
|
result = []
|
||||||
for agent_trans, agent in results:
|
for agent_trans, agent in results:
|
||||||
|
try:
|
||||||
|
status_enum = TransactionStatus(agent_trans.status)
|
||||||
|
except ValueError:
|
||||||
|
# Если статус из БД не соответствует Enum, используем статус ERROR
|
||||||
|
status_enum = TransactionStatus.ERROR
|
||||||
result.append({
|
result.append({
|
||||||
"id": agent_trans.transaction_group, # Используем transaction_group как ID транзакции группы
|
"id": agent_trans.transaction_group, # Используем id, как и запрошено
|
||||||
"amount": agent_trans.amount,
|
"amount": agent_trans.amount,
|
||||||
"agent": agent.name if agent else None, # Имя агента из join
|
"agent": agent.name if agent else None,
|
||||||
"status": agent_trans.status,
|
"status": status_enum,
|
||||||
"create_dttm": agent_trans.create_dttm,
|
"create_dttm": agent_trans.create_dttm,
|
||||||
"update_dttm": agent_trans.update_dttm,
|
"update_dttm": agent_trans.update_dttm,
|
||||||
})
|
})
|
||||||
return result
|
return BillingPayoutsTransactionsResponse(items=result)
|
||||||
|
|
||||||
@app.get("/billing/chart/stat", tags=["bff"])
|
@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)):
|
def get_billing_chart_stat(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)):
|
||||||
# Группируем агентские транзакции по дате (день) и статусу
|
# Группируем агентские транзакции по дате (день) и статусу
|
||||||
result = db.exec(
|
result = db.exec(
|
||||||
@ -562,7 +568,7 @@ def get_billing_chart_stat(current_account: Account = Depends(get_current_accoun
|
|||||||
func.strftime('%Y-%m-%d', AgentTransaction.create_dttm).label('date'),
|
func.strftime('%Y-%m-%d', AgentTransaction.create_dttm).label('date'),
|
||||||
AgentTransaction.status.label('status'),
|
AgentTransaction.status.label('status'),
|
||||||
func.count(AgentTransaction.id).label('count')
|
func.count(AgentTransaction.id).label('count')
|
||||||
).group_by(
|
).join(TgAgent).where(TgAgent.company_id == current_account.company_id).group_by(
|
||||||
func.strftime('%Y-%m-%d', AgentTransaction.create_dttm),
|
func.strftime('%Y-%m-%d', AgentTransaction.create_dttm),
|
||||||
AgentTransaction.status
|
AgentTransaction.status
|
||||||
).order_by(
|
).order_by(
|
||||||
@ -574,26 +580,26 @@ def get_billing_chart_stat(current_account: Account = Depends(get_current_accoun
|
|||||||
{"date": row.date, "status": row.status, "count": row.count}
|
{"date": row.date, "status": row.status, "count": row.count}
|
||||||
for row in result
|
for row in result
|
||||||
]
|
]
|
||||||
return JSONResponse(content=data)
|
return BillingChartStatResponse(items=data)
|
||||||
|
|
||||||
@app.get("/billing/chart/pie", tags=["bff"])
|
@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)):
|
def get_billing_chart_pie(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)):
|
||||||
# Группируем агентские транзакции по статусу
|
# Группируем агентские транзакции по статусу
|
||||||
result = db.exec(
|
result = db.exec(
|
||||||
select(
|
select(
|
||||||
AgentTransaction.status.label('status'),
|
AgentTransaction.status.label('status'),
|
||||||
func.count(AgentTransaction.id).label('count')
|
func.count(AgentTransaction.id).label('count')
|
||||||
).group_by(AgentTransaction.status)
|
).join(TgAgent).where(TgAgent.company_id == current_account.company_id).group_by(AgentTransaction.status)
|
||||||
).all()
|
).all()
|
||||||
data = [
|
data = [
|
||||||
{"status": row.status, "count": row.count}
|
{"status": row.status, "count": row.count}
|
||||||
for row in result
|
for row in result
|
||||||
]
|
]
|
||||||
return JSONResponse(content=data)
|
return BillingChartPieResponse(items=data)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.post("/tg_auth", tags=["partner-tg"])
|
@app.post("/tg_auth", tags=["partner-tg"], response_model=TgAuthResponse)
|
||||||
def tg_auth(hash: str = Body(..., embed=True), db: Session = Depends(get_db)):
|
def tg_auth(hash: str = Body(..., embed=True), db: Session = Depends(get_db)):
|
||||||
tg_agent = db.exec(select(TgAgent).where(TgAgent.hash == hash)).first()
|
tg_agent = db.exec(select(TgAgent).where(TgAgent.hash == hash)).first()
|
||||||
if not tg_agent:
|
if not tg_agent:
|
||||||
@ -612,14 +618,14 @@ def get_account_by_login(db: Session, login: str) -> Optional[Account]:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/account", tags=["bff"])
|
@app.get("/account", tags=["bff", "account"], response_model=AccountResponse)
|
||||||
def get_account(current_account: Account = Depends(get_current_account)):
|
def get_account(current_account: Account = Depends(get_current_account)):
|
||||||
return {
|
return {
|
||||||
"firstName": current_account.firstName,
|
"firstName": current_account.firstName,
|
||||||
"surname": current_account.surname
|
"surname": current_account.surname
|
||||||
}
|
}
|
||||||
|
|
||||||
@app.get("/account/profile", tags=["bff"])
|
@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)):
|
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()
|
company = db.exec(select(Company).where(Company.id == current_account.company_id)).first()
|
||||||
if not company:
|
if not company:
|
||||||
@ -637,7 +643,7 @@ def get_account_profile(current_account: Account = Depends(get_current_account),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@app.post("/account/profile", tags=["bff"])
|
@app.post("/account/profile", tags=["bff", "account"], response_model=AccountProfileUpdateResponse)
|
||||||
def update_account_profile(
|
def update_account_profile(
|
||||||
req: AccountProfileUpdateRequest,
|
req: AccountProfileUpdateRequest,
|
||||||
current_account: Account = Depends(get_current_account),
|
current_account: Account = Depends(get_current_account),
|
||||||
@ -656,7 +662,7 @@ def update_account_profile(
|
|||||||
db.refresh(current_account)
|
db.refresh(current_account)
|
||||||
return {"msg": "Профиль обновлён успешно"}
|
return {"msg": "Профиль обновлён успешно"}
|
||||||
|
|
||||||
@app.post("/account/password", tags=["bff"])
|
@app.post("/account/password", tags=["bff", "account"], response_model=AccountPasswordChangeResponse)
|
||||||
def change_account_password(
|
def change_account_password(
|
||||||
req: AccountPasswordChangeRequest,
|
req: AccountPasswordChangeRequest,
|
||||||
current_account: Account = Depends(get_current_account),
|
current_account: Account = Depends(get_current_account),
|
||||||
@ -679,7 +685,7 @@ def change_account_password(
|
|||||||
|
|
||||||
# --- Новый функционал для агентских транзакций партнера ---
|
# --- Новый функционал для агентских транзакций партнера ---
|
||||||
|
|
||||||
@app.get("/account/agent-transaction", response_model=List[AgentTransactionResponse], tags=["bff"])
|
@app.get("/account/agent-transaction", response_model=List[AgentTransactionResponse], tags=["bff", "account"])
|
||||||
def get_account_agent_transactions(
|
def get_account_agent_transactions(
|
||||||
statuses: Optional[List[TransactionStatus]] = Query(None), # Изменено на List[TransactionStatus]
|
statuses: Optional[List[TransactionStatus]] = Query(None), # Изменено на List[TransactionStatus]
|
||||||
date_start: str = Query(None), # Добавлен параметр date_start
|
date_start: str = Query(None), # Добавлен параметр date_start
|
||||||
@ -733,7 +739,7 @@ class AutoApproveSettingsRequest(BaseModel):
|
|||||||
auto_approve: bool
|
auto_approve: bool
|
||||||
apply_to_current: Optional[bool] = False
|
apply_to_current: Optional[bool] = False
|
||||||
|
|
||||||
@app.get("/account/auto-approve", tags=["bff"])
|
@app.get("/account/auto-approve", tags=["bff", "account"], response_model=AutoApproveSettingsGetResponse)
|
||||||
def get_auto_approve_settings(
|
def get_auto_approve_settings(
|
||||||
current_account: Account = Depends(get_current_account),
|
current_account: Account = Depends(get_current_account),
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
@ -746,7 +752,7 @@ def get_auto_approve_settings(
|
|||||||
raise HTTPException(status_code=404, detail="Компания не найдена")
|
raise HTTPException(status_code=404, detail="Компания не найдена")
|
||||||
return {"auto_approve_transactions": company.auto_approve_transactions}
|
return {"auto_approve_transactions": company.auto_approve_transactions}
|
||||||
|
|
||||||
@app.post("/account/auto-approve", tags=["bff"])
|
@app.post("/account/auto-approve", tags=["bff", "account"], response_model=AutoApproveSettingsUpdateResponse)
|
||||||
def update_auto_approve_settings(
|
def update_auto_approve_settings(
|
||||||
req: AutoApproveSettingsRequest,
|
req: AutoApproveSettingsRequest,
|
||||||
current_account: Account = Depends(get_current_account),
|
current_account: Account = Depends(get_current_account),
|
||||||
@ -798,7 +804,7 @@ def update_auto_approve_settings(
|
|||||||
class ApproveTransactionsRequest(BaseModel):
|
class ApproveTransactionsRequest(BaseModel):
|
||||||
transaction_ids: List[uuid.UUID]
|
transaction_ids: List[uuid.UUID]
|
||||||
|
|
||||||
@app.post("/account/approve-transactions", tags=["bff"])
|
@app.post("/account/approve-transactions", tags=["bff", "account"], response_model=ApproveTransactionsResult)
|
||||||
def approve_agent_transactions(
|
def approve_agent_transactions(
|
||||||
req: ApproveTransactionsRequest,
|
req: ApproveTransactionsRequest,
|
||||||
current_account: Account = Depends(get_current_account),
|
current_account: Account = Depends(get_current_account),
|
||||||
|
|||||||
32
models.py
32
models.py
@ -1,32 +0,0 @@
|
|||||||
from pydantic import BaseModel, Field
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from sqlmodel import SQLModel
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#API models
|
|
||||||
class Token(BaseModel):
|
|
||||||
access_token: str
|
|
||||||
token_type: str
|
|
||||||
|
|
||||||
class RefResponse(BaseModel):
|
|
||||||
ref: str
|
|
||||||
description: str
|
|
||||||
|
|
||||||
class RefAddRequest(BaseModel):
|
|
||||||
description: str
|
|
||||||
|
|
||||||
class TokenRequest(BaseModel):
|
|
||||||
tg_id: int
|
|
||||||
|
|
||||||
class RegisterRequest(BaseModel):
|
|
||||||
tg_id: int
|
|
||||||
chat_id: Optional[int] = None
|
|
||||||
phone: Optional[str] = None
|
|
||||||
name: Optional[str] = None
|
|
||||||
login: Optional[str] = None
|
|
||||||
company_key: str
|
|
||||||
40
tg_models.py
Normal file
40
tg_models.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from typing import Optional, List
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
|
|
||||||
|
# TG Models
|
||||||
|
class RefResponse(BaseModel):
|
||||||
|
ref: str
|
||||||
|
description: str
|
||||||
|
|
||||||
|
class RefAddRequest(BaseModel):
|
||||||
|
description: str
|
||||||
|
|
||||||
|
class TokenRequest(BaseModel):
|
||||||
|
tg_id: int
|
||||||
|
|
||||||
|
class RegisterRequest(BaseModel):
|
||||||
|
tg_id: int
|
||||||
|
chat_id: Optional[int] = None
|
||||||
|
phone: Optional[str] = None
|
||||||
|
name: Optional[str] = None
|
||||||
|
login: Optional[str] = None
|
||||||
|
company_key: str
|
||||||
|
|
||||||
|
# New Response Models for TG APIs
|
||||||
|
class RefAddResponse(BaseModel):
|
||||||
|
ref: str
|
||||||
|
|
||||||
|
class RefStatItem(BaseModel):
|
||||||
|
description: str
|
||||||
|
sales: int
|
||||||
|
income: float
|
||||||
|
|
||||||
|
class RefStatResponse(BaseModel):
|
||||||
|
refData: List[RefStatItem]
|
||||||
|
|
||||||
|
class StatResponse(BaseModel):
|
||||||
|
totalSales: int
|
||||||
|
totalIncome: float
|
||||||
|
availableWithdrawal: float
|
||||||
Loading…
x
Reference in New Issue
Block a user