from fastapi import FastAPI, Depends, HTTPException, status, Header from fastapi.security import OAuth2PasswordBearer from sqlmodel import Session, select from typing import Optional from datetime import datetime import hashlib import uuid from sql_models import Company, IntegrationToken, Ref, Sale, AgentTransaction, PartnerTransaction, AgentBalance, TgAgent, CompanyBalance from integration_models import Token, SaleCreateRequest, SaleCreateResponse, TransactionStatus from helpers_bff import AUTH_DB_ENGINE, get_integration_db, create_integration_jwt_token, get_current_company_from_jwt app = FastAPI() #7c06945b-f4b8-4929-8350-b9841405a609 @app.post("/token", tags=["integration"], response_model=Token) async def get_token_for_api_key( x_api_key: str = Header(..., alias="X-API-Key"), db: Session = Depends(get_integration_db) ): """ Обменивает API-ключ на JWT токен. """ if not x_api_key: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="API-ключ не предоставлен", headers={"WWW-Authenticate": "Bearer"}, ) api_key_hash = hashlib.sha256(x_api_key.encode()).hexdigest() integration_token_db = db.exec( select(IntegrationToken).where(IntegrationToken.token_hash == api_key_hash) ).first() if not integration_token_db: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Неверный API-ключ", headers={"WWW-Authenticate": "Bearer"}, ) # Обновляем use_dttm токена integration_token_db.use_dttm = datetime.utcnow() db.add(integration_token_db) db.commit() db.refresh(integration_token_db) jwt_token = create_integration_jwt_token(integration_token_db.company_id) return {"access_token": jwt_token, "token_type": "bearer"} @app.post("/sale", tags=["integration"], response_model=SaleCreateResponse) async def create_sale( req: SaleCreateRequest, company: Company = Depends(get_current_company_from_jwt), # Используем новую зависимость db: Session = Depends(get_integration_db) ): """ Регистрирует новую продажу в системе. """ # 1. Найти Ref по `ref` и `company.id` # Сначала находим TgAgent, связанный с компанией, затем Ref tg_agent = db.exec( select(TgAgent) .join(Ref) .where(TgAgent.company_id == company.id) .where(Ref.ref == req.ref) ).first() if not tg_agent: raise HTTPException(status_code=404, detail="Реферальная ссылка не найдена или не принадлежит данной компании") referral = db.exec(select(Ref).where(Ref.ref == req.ref).where(Ref.tg_agent_id == tg_agent.id)).first() if not referral: raise HTTPException(status_code=404, detail="Реферальная ссылка не найдена") # 2. Проверить, что sale_id уникален для данной компании existing_sale = db.exec( select(Sale) .where(Sale.company_id == company.id) .where(Sale.sale_id == req.sale_id) ).first() if existing_sale: raise HTTPException(status_code=400, detail="Продажа с таким sale_id уже существует для данной компании") # 3. Рассчитать crediting crediting_amount = req.cost * (company.agent_commission / 100.0) # 4. Создать Sale new_sale = Sale( cost=req.cost, crediting=crediting_amount, ref=referral.id, sale_id=req.sale_id, company_id=company.id, sale_dttm=datetime.utcnow() ) db.add(new_sale) db.commit() db.refresh(new_sale) # 5. Обновить AgentBalance и CompanyBalance # AgentBalance agent_balance = db.exec(select(AgentBalance).where(AgentBalance.tg_agent_id == tg_agent.id)).first() if not agent_balance: agent_balance = AgentBalance(tg_agent_id=tg_agent.id, available_balance=0.0, frozen_balance=0.0) db.add(agent_balance) db.commit() db.refresh(agent_balance) # CompanyBalance company_balance = db.exec(select(CompanyBalance).where(CompanyBalance.company_id == company.id)).first() if not company_balance: company_balance = CompanyBalance(company_id=company.id, available_balance=0.0, pending_balance=0.0) db.add(company_balance) db.commit() db.refresh(company_balance) # Создать AgentTransaction agent_transaction_status = TransactionStatus.NEW if company.auto_approve_transactions else TransactionStatus.WAITING agent_transaction = AgentTransaction( tg_agent_id=tg_agent.id, amount=crediting_amount, status=agent_transaction_status.value, transaction_group=uuid.uuid4() ) db.add(agent_transaction) db.commit() db.refresh(agent_transaction) # Создать PartnerTransaction partner_transaction_status = TransactionStatus.NEW if company.auto_approve_transactions else TransactionStatus.PROCESS partner_transaction = PartnerTransaction( company_id=company.id, type="sale_crediting", amount=crediting_amount, status=partner_transaction_status.value, transaction_group=agent_transaction.transaction_group, agent_transaction_id=agent_transaction.id ) db.add(partner_transaction) db.commit() db.refresh(partner_transaction) # Обновление балансов в зависимости от auto_approve_transactions if company.auto_approve_transactions: agent_balance.available_balance += crediting_amount company_balance.available_balance -= crediting_amount company_balance.updated_dttm = datetime.utcnow() else: agent_balance.frozen_balance += crediting_amount company_balance.pending_balance -= crediting_amount company_balance.updated_dttm = datetime.utcnow() db.add(agent_balance) db.add(company_balance) db.commit() db.refresh(agent_balance) db.refresh(company_balance) return { "msg": "Продажа успешно зарегистрирована", "sale_id": new_sale.sale_id, "crediting": new_sale.crediting }