Compare commits
No commits in common. "5d14969f822ea592c8d01ff1a6fe9bee4aa5ecb0" and "8c6fadb1801a6186cbcb38c334d4765fd517f6b1" have entirely different histories.
5d14969f82
...
8c6fadb180
@ -204,9 +204,9 @@ def fill_db():
|
|||||||
session.refresh(balance)
|
session.refresh(balance)
|
||||||
|
|
||||||
# 5.3 AgentTransactions and PartnerTransactions
|
# 5.3 AgentTransactions and PartnerTransactions
|
||||||
AGENT_TRANSACTION_STATUSES = ['waiting', 'process', 'done', 'reject', 'error', 'new']
|
AGENT_TRANSACTION_STATUSES = ['waiting', 'process', 'done', 'reject', 'error']
|
||||||
PARTNER_TRANSACTION_TYPES = ['deposit', 'agent_payout', 'service_fee']
|
PARTNER_TRANSACTION_TYPES = ['deposit', 'agent_payout', 'service_fee']
|
||||||
PARTNER_TRANSACTION_STATUSES = ['process', 'done', 'error', 'new']
|
PARTNER_TRANSACTION_STATUSES = ['process', 'done', 'error']
|
||||||
|
|
||||||
for tg_agent in tg_agents:
|
for tg_agent in tg_agents:
|
||||||
# Генерируем несколько групп транзакций для каждого агента
|
# Генерируем несколько групп транзакций для каждого агента
|
||||||
|
|||||||
159
main.py
159
main.py
@ -26,7 +26,6 @@ class Company(SQLModel, table=True):
|
|||||||
key: str = Field(index=True, unique=True)
|
key: str = Field(index=True, unique=True)
|
||||||
create_dttm: datetime = Field(default_factory=datetime.utcnow)
|
create_dttm: datetime = Field(default_factory=datetime.utcnow)
|
||||||
update_dttm: datetime = Field(default_factory=datetime.utcnow)
|
update_dttm: datetime = Field(default_factory=datetime.utcnow)
|
||||||
auto_approve_transactions: bool = Field(default=False) # Новое поле для автоподтверждения
|
|
||||||
|
|
||||||
class TgAgent(SQLModel, table=True):
|
class TgAgent(SQLModel, table=True):
|
||||||
id: Optional[int] = Field(default=None, primary_key=True)
|
id: Optional[int] = Field(default=None, primary_key=True)
|
||||||
@ -125,7 +124,6 @@ class TransactionStatus(str, Enum): # Определяем Enum для стат
|
|||||||
DONE = 'done'
|
DONE = 'done'
|
||||||
REJECT = 'reject'
|
REJECT = 'reject'
|
||||||
ERROR = 'error'
|
ERROR = 'error'
|
||||||
NEW = 'new' # Новый статус
|
|
||||||
|
|
||||||
|
|
||||||
# Новая модель ответа для агентских транзакций с именем агента
|
# Новая модель ответа для агентских транзакций с именем агента
|
||||||
@ -162,24 +160,6 @@ def get_db():
|
|||||||
with Session(AUTH_DB_ENGINE) as session:
|
with Session(AUTH_DB_ENGINE) as session:
|
||||||
yield session
|
yield session
|
||||||
|
|
||||||
def get_current_account(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
|
|
||||||
credentials_exception = HTTPException(
|
|
||||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
||||||
detail="Could not validate credentials",
|
|
||||||
headers={"WWW-Authenticate": "Bearer"},
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
|
||||||
login: str = payload.get("sub")
|
|
||||||
if login is None:
|
|
||||||
raise credentials_exception
|
|
||||||
except InvalidTokenError:
|
|
||||||
raise credentials_exception
|
|
||||||
account = get_account_by_login(db, login)
|
|
||||||
if account is None:
|
|
||||||
raise credentials_exception
|
|
||||||
return account
|
|
||||||
|
|
||||||
# Авторизация
|
# Авторизация
|
||||||
async def get_current_tg_agent(request: Request, db: Session = Depends(get_db)):
|
async def get_current_tg_agent(request: Request, db: Session = Depends(get_db)):
|
||||||
credentials_exception = HTTPException(
|
credentials_exception = HTTPException(
|
||||||
@ -331,7 +311,7 @@ def get_stat(current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Sess
|
|||||||
}
|
}
|
||||||
|
|
||||||
@app.get("/dashboard/cards", tags=["bff"])
|
@app.get("/dashboard/cards", tags=["bff"])
|
||||||
def get_dashboard_cards(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)):
|
def get_dashboard_cards(db: Session = Depends(get_db)):
|
||||||
# 1. Общий доход - сумма всех Sale.cost
|
# 1. Общий доход - сумма всех Sale.cost
|
||||||
total_revenue = db.exec(select(Sale)).all()
|
total_revenue = db.exec(select(Sale)).all()
|
||||||
totalRevenue = sum(sale.cost for sale in total_revenue)
|
totalRevenue = sum(sale.cost for sale in total_revenue)
|
||||||
@ -359,7 +339,7 @@ def get_dashboard_cards(current_account: Account = Depends(get_current_account),
|
|||||||
}
|
}
|
||||||
|
|
||||||
@app.get("/dashboard/chart/total", tags=["bff"])
|
@app.get("/dashboard/chart/total", tags=["bff"])
|
||||||
def get_dashboard_chart_total(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)):
|
def get_dashboard_chart_total(db: Session = Depends(get_db)):
|
||||||
# Группируем продажи по дате (день)
|
# Группируем продажи по дате (день)
|
||||||
result = db.exec(
|
result = db.exec(
|
||||||
select(
|
select(
|
||||||
@ -377,7 +357,7 @@ def get_dashboard_chart_total(current_account: Account = Depends(get_current_acc
|
|||||||
return JSONResponse(content=data)
|
return JSONResponse(content=data)
|
||||||
|
|
||||||
@app.get("/dashboard/chart/agent", tags=["bff"])
|
@app.get("/dashboard/chart/agent", tags=["bff"])
|
||||||
def get_dashboard_chart_agent(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)):
|
def get_dashboard_chart_agent(db: Session = Depends(get_db)):
|
||||||
# Получаем всех агентов
|
# Получаем всех агентов
|
||||||
agents = db.exec(select(TgAgent)).all()
|
agents = db.exec(select(TgAgent)).all()
|
||||||
result = []
|
result = []
|
||||||
@ -408,7 +388,6 @@ 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),
|
|
||||||
):
|
):
|
||||||
agents_query = select(TgAgent)
|
agents_query = select(TgAgent)
|
||||||
if date_start:
|
if date_start:
|
||||||
@ -448,7 +427,6 @@ 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),
|
|
||||||
):
|
):
|
||||||
refs_query = select(Ref)
|
refs_query = select(Ref)
|
||||||
if date_start:
|
if date_start:
|
||||||
@ -476,7 +454,6 @@ 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),
|
|
||||||
):
|
):
|
||||||
sales_query = select(Sale)
|
sales_query = select(Sale)
|
||||||
if date_start:
|
if date_start:
|
||||||
@ -504,7 +481,7 @@ def get_sales_stat(
|
|||||||
return JSONResponse(content=result)
|
return JSONResponse(content=result)
|
||||||
|
|
||||||
@app.get("/billing/cards", tags=["bff"])
|
@app.get("/billing/cards", tags=["bff"])
|
||||||
def get_billing_cards(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)):
|
def get_billing_cards(db: Session = Depends(get_db)):
|
||||||
# 1. cost - Общий заработок (сумма всех Sale.cost)
|
# 1. cost - Общий заработок (сумма всех Sale.cost)
|
||||||
sales = db.exec(select(Sale)).all()
|
sales = db.exec(select(Sale)).all()
|
||||||
cost = sum(sale.cost for sale in sales)
|
cost = sum(sale.cost for sale in sales)
|
||||||
@ -528,7 +505,6 @@ 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),
|
||||||
date_end: str = Query(None),
|
date_end: str = Query(None),
|
||||||
current_account: Account = Depends(get_current_account),
|
|
||||||
):
|
):
|
||||||
# Используем AgentTransaction вместо Transaction
|
# Используем AgentTransaction вместо Transaction
|
||||||
# Явно выбираем обе модели для корректной распаковки
|
# Явно выбираем обе модели для корректной распаковки
|
||||||
@ -555,7 +531,7 @@ def get_billing_payouts_transactions(
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
@app.get("/billing/chart/stat", tags=["bff"])
|
@app.get("/billing/chart/stat", tags=["bff"])
|
||||||
def get_billing_chart_stat(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)):
|
def get_billing_chart_stat(db: Session = Depends(get_db)):
|
||||||
# Группируем агентские транзакции по дате (день) и статусу
|
# Группируем агентские транзакции по дате (день) и статусу
|
||||||
result = db.exec(
|
result = db.exec(
|
||||||
select(
|
select(
|
||||||
@ -577,7 +553,7 @@ def get_billing_chart_stat(current_account: Account = Depends(get_current_accoun
|
|||||||
return JSONResponse(content=data)
|
return JSONResponse(content=data)
|
||||||
|
|
||||||
@app.get("/billing/chart/pie", tags=["bff"])
|
@app.get("/billing/chart/pie", tags=["bff"])
|
||||||
def get_billing_chart_pie(current_account: Account = Depends(get_current_account), db: Session = Depends(get_db)):
|
def get_billing_chart_pie(db: Session = Depends(get_db)):
|
||||||
# Группируем агентские транзакции по статусу
|
# Группируем агентские транзакции по статусу
|
||||||
result = db.exec(
|
result = db.exec(
|
||||||
select(
|
select(
|
||||||
@ -610,7 +586,23 @@ def get_account_by_login(db: Session, login: str) -> Optional[Account]:
|
|||||||
statement = select(Account).where(Account.login == login)
|
statement = select(Account).where(Account.login == login)
|
||||||
return db.exec(statement).first()
|
return db.exec(statement).first()
|
||||||
|
|
||||||
|
def get_current_account(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
|
||||||
|
credentials_exception = HTTPException(
|
||||||
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||||
|
detail="Could not validate credentials",
|
||||||
|
headers={"WWW-Authenticate": "Bearer"},
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
||||||
|
login: str = payload.get("sub")
|
||||||
|
if login is None:
|
||||||
|
raise credentials_exception
|
||||||
|
except InvalidTokenError:
|
||||||
|
raise credentials_exception
|
||||||
|
account = get_account_by_login(db, login)
|
||||||
|
if account is None:
|
||||||
|
raise credentials_exception
|
||||||
|
return account
|
||||||
|
|
||||||
@app.get("/account", tags=["bff"])
|
@app.get("/account", tags=["bff"])
|
||||||
def get_account(current_account: Account = Depends(get_current_account)):
|
def get_account(current_account: Account = Depends(get_current_account)):
|
||||||
@ -727,108 +719,3 @@ def get_account_agent_transactions(
|
|||||||
)
|
)
|
||||||
|
|
||||||
return agent_transactions_response
|
return agent_transactions_response
|
||||||
|
|
||||||
# Модель запроса для POST /account/auto-approve
|
|
||||||
class AutoApproveSettingsRequest(BaseModel):
|
|
||||||
auto_approve: bool
|
|
||||||
apply_to_current: Optional[bool] = False
|
|
||||||
|
|
||||||
@app.get("/account/auto-approve", tags=["bff"])
|
|
||||||
def get_auto_approve_settings(
|
|
||||||
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="Компания не найдена")
|
|
||||||
return {"auto_approve_transactions": company.auto_approve_transactions}
|
|
||||||
|
|
||||||
@app.post("/account/auto-approve", tags=["bff"])
|
|
||||||
def update_auto_approve_settings(
|
|
||||||
req: AutoApproveSettingsRequest,
|
|
||||||
current_account: Account = Depends(get_current_account),
|
|
||||||
db: Session = Depends(get_db)
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Обновляет настройку автоматического подтверждения для компании пользователя.
|
|
||||||
При необходимости переводит транзакции из 'waiting' в 'new'.
|
|
||||||
"""
|
|
||||||
company = db.exec(select(Company).where(Company.id == current_account.company_id)).first()
|
|
||||||
if not company:
|
|
||||||
raise HTTPException(status_code=404, detail="Компания не найдена")
|
|
||||||
|
|
||||||
company.auto_approve_transactions = req.auto_approve
|
|
||||||
company.update_dttm = datetime.utcnow()
|
|
||||||
db.add(company)
|
|
||||||
|
|
||||||
if req.apply_to_current and req.auto_approve: # Применяем только если авто-аппрув включается и запрошено применение к текущим
|
|
||||||
# Находим все агентские транзакции компании в статусе 'waiting'
|
|
||||||
agent_transactions_to_update = db.exec(
|
|
||||||
select(AgentTransaction)
|
|
||||||
.join(TgAgent)
|
|
||||||
.where(TgAgent.company_id == company.id)
|
|
||||||
.where(AgentTransaction.status == TransactionStatus.WAITING)
|
|
||||||
).all()
|
|
||||||
|
|
||||||
for agent_trans in agent_transactions_to_update:
|
|
||||||
agent_trans.status = TransactionStatus.NEW
|
|
||||||
agent_trans.update_dttm = datetime.utcnow()
|
|
||||||
db.add(agent_trans)
|
|
||||||
|
|
||||||
# Находим соответствующие партнерские транзакции и обновляем их статус
|
|
||||||
partner_transactions_to_update = db.exec(
|
|
||||||
select(PartnerTransaction)
|
|
||||||
.where(PartnerTransaction.agent_transaction_id == agent_trans.id) # Используем связь по ID
|
|
||||||
.where(PartnerTransaction.status == TransactionStatus.PROCESS) # Предполагаем, что связанные партнерские транзакции в статусе PROCESS
|
|
||||||
).all()
|
|
||||||
for partner_trans in partner_transactions_to_update:
|
|
||||||
partner_trans.status = TransactionStatus.NEW
|
|
||||||
partner_trans.update_dttm = datetime.utcnow()
|
|
||||||
db.add(partner_trans)
|
|
||||||
|
|
||||||
db.commit()
|
|
||||||
db.refresh(company)
|
|
||||||
|
|
||||||
return {"msg": "Настройка автоматического подтверждения обновлена", "auto_approve_transactions": company.auto_approve_transactions}
|
|
||||||
|
|
||||||
# Модель запроса для POST /account/approve-transactions
|
|
||||||
class ApproveTransactionsRequest(BaseModel):
|
|
||||||
transaction_ids: List[uuid.UUID]
|
|
||||||
|
|
||||||
@app.post("/account/approve-transactions", tags=["bff"])
|
|
||||||
def approve_agent_transactions(
|
|
||||||
req: ApproveTransactionsRequest,
|
|
||||||
current_account: Account = Depends(get_current_account),
|
|
||||||
db: Session = Depends(get_db)
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Утверждение выбранных агентских транзакций для компании текущего пользователя.
|
|
||||||
Переводит транзакции из статуса 'waiting' в 'new'.
|
|
||||||
"""
|
|
||||||
company_id = current_account.company_id
|
|
||||||
approved_count = 0
|
|
||||||
|
|
||||||
if not req.transaction_ids:
|
|
||||||
return {"msg": "Нет транзакций для утверждения", "approved_count": 0}
|
|
||||||
|
|
||||||
# Find transactions belonging to the company and with specified IDs and statuses
|
|
||||||
transactions_to_approve = db.exec(
|
|
||||||
select(AgentTransaction)
|
|
||||||
.join(TgAgent)
|
|
||||||
.where(TgAgent.company_id == company_id)
|
|
||||||
.where(AgentTransaction.transaction_group.in_(req.transaction_ids))
|
|
||||||
.where(AgentTransaction.status == TransactionStatus.WAITING) # Утверждаем только транзакции в статусе 'waiting'
|
|
||||||
).all()
|
|
||||||
|
|
||||||
for agent_trans in transactions_to_approve:
|
|
||||||
agent_trans.status = TransactionStatus.NEW # Переводим в статус 'new'
|
|
||||||
agent_trans.update_dttm = datetime.utcnow()
|
|
||||||
db.add(agent_trans)
|
|
||||||
approved_count += 1
|
|
||||||
|
|
||||||
db.commit()
|
|
||||||
|
|
||||||
return {"msg": f"Переведено в статус NEW {approved_count} транзакций", "approved_count": approved_count}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user