From 8a8b111f40fcec12a8873b82d097532ed0263a80 Mon Sep 17 00:00:00 2001 From: Redsandyg Date: Sat, 7 Jun 2025 12:25:17 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B5=20=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D1=82=D1=83=D1=81=D1=8B=20=D0=B4=D0=BB=D1=8F=20=D0=B0?= =?UTF-8?q?=D0=B3=D0=B5=D0=BD=D1=82=D1=81=D0=BA=D0=B8=D1=85=20=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=B0=D1=80=D1=82=D0=BD=D0=B5=D1=80=D1=81=D0=BA=D0=B8?= =?UTF-8?q?=D1=85=20=D1=82=D1=80=D0=B0=D0=BD=D0=B7=D0=B0=D0=BA=D1=86=D0=B8?= =?UTF-8?q?=D0=B9,=20=D0=B0=20=D1=82=D0=B0=D0=BA=D0=B6=D0=B5=20=D1=80?= =?UTF-8?q?=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D1=8B=20?= =?UTF-8?q?=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B8=20=D0=B4=D0=BB=D1=8F?= =?UTF-8?q?=20=D0=B0=D0=B2=D1=82=D0=BE=D0=BC=D0=B0=D1=82=D0=B8=D1=87=D0=B5?= =?UTF-8?q?=D1=81=D0=BA=D0=BE=D0=B3=D0=BE=20=D0=BF=D0=BE=D0=B4=D1=82=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D0=B6=D0=B4=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=82=D1=80?= =?UTF-8?q?=D0=B0=D0=BD=D0=B7=D0=B0=D0=BA=D1=86=D0=B8=D0=B9.=20=D0=9E?= =?UTF-8?q?=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BC=D0=BE?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D0=B8=20=D0=B8=20API=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D1=83=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA=D0=B0=D0=BC?= =?UTF-8?q?=D0=B8=20=D0=B0=D0=B2=D1=82=D0=BE=D0=BF=D0=BE=D0=B4=D1=82=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D0=B6=D0=B4=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B8=20?= =?UTF-8?q?=D1=83=D1=82=D0=B2=D0=B5=D1=80=D0=B6=D0=B4=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D1=82=D1=80=D0=B0=D0=BD=D0=B7=D0=B0=D0=BA=D1=86=D0=B8?= =?UTF-8?q?=D0=B9.=20=D0=A3=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=D1=8B=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=80=D0=B8?= =?UTF-8?q?=D0=B8=20=D0=B4=D0=BB=D1=8F=20=D1=8F=D1=81=D0=BD=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D0=B8=20=D0=BA=D0=BE=D0=B4=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fill_db.py | 4 +- main.py | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/fill_db.py b/fill_db.py index 241a248..bac4e2f 100644 --- a/fill_db.py +++ b/fill_db.py @@ -204,9 +204,9 @@ def fill_db(): session.refresh(balance) # 5.3 AgentTransactions and PartnerTransactions - AGENT_TRANSACTION_STATUSES = ['waiting', 'process', 'done', 'reject', 'error'] + AGENT_TRANSACTION_STATUSES = ['waiting', 'process', 'done', 'reject', 'error', 'new'] PARTNER_TRANSACTION_TYPES = ['deposit', 'agent_payout', 'service_fee'] - PARTNER_TRANSACTION_STATUSES = ['process', 'done', 'error'] + PARTNER_TRANSACTION_STATUSES = ['process', 'done', 'error', 'new'] for tg_agent in tg_agents: # Генерируем несколько групп транзакций для каждого агента diff --git a/main.py b/main.py index bf20a99..4ec9a6c 100644 --- a/main.py +++ b/main.py @@ -26,6 +26,7 @@ class Company(SQLModel, table=True): key: str = Field(index=True, unique=True) create_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): id: Optional[int] = Field(default=None, primary_key=True) @@ -124,6 +125,7 @@ class TransactionStatus(str, Enum): # Определяем Enum для стат DONE = 'done' REJECT = 'reject' ERROR = 'error' + NEW = 'new' # Новый статус # Новая модель ответа для агентских транзакций с именем агента @@ -719,3 +721,108 @@ def get_account_agent_transactions( ) 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}