83 lines
2.8 KiB
Python
83 lines
2.8 KiB
Python
"""Escrow endpoints (гарант)."""
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy import select
|
|
|
|
from app.core.database import get_db
|
|
from app.schemas.escrow import EscrowCreate, EscrowRelease
|
|
from app.models.escrow import EscrowTransaction
|
|
from app.models.project import Project
|
|
|
|
router = APIRouter(prefix="/api/escrow", tags=["escrow"])
|
|
|
|
|
|
@router.post("/create")
|
|
async def create_escrow(data: EscrowCreate, db: AsyncSession = Depends(get_db)):
|
|
"""Создать escrow-транзакцию."""
|
|
|
|
result = await db.execute(select(Project).where(Project.id == data.project_id))
|
|
project = result.scalar_one_or_none()
|
|
|
|
if not project:
|
|
raise HTTPException(status_code=404, detail="Проект не найден")
|
|
|
|
transaction = EscrowTransaction(
|
|
project_id=data.project_id,
|
|
client_id=data.client_id,
|
|
freelancer_id=data.freelancer_id,
|
|
amount=data.amount,
|
|
status="pending",
|
|
)
|
|
db.add(transaction)
|
|
await db.commit()
|
|
await db.refresh(transaction)
|
|
|
|
return {
|
|
"id": str(transaction.id),
|
|
"status": transaction.status,
|
|
"amount": float(transaction.amount),
|
|
"payment_url": f"https://stripe.com/pay/{transaction.id}", # Stripe redirect
|
|
}
|
|
|
|
|
|
@router.post("/release")
|
|
async def release_escrow(data: EscrowRelease, db: AsyncSession = Depends(get_db)):
|
|
"""Освободить средства фрилансеру."""
|
|
|
|
result = await db.execute(select(EscrowTransaction).where(EscrowTransaction.id == data.transaction_id))
|
|
transaction = result.scalar_one_or_none()
|
|
|
|
if not transaction or transaction.status != "locked":
|
|
raise HTTPException(status_code=400, detail="Транзакция не может быть разблокирована")
|
|
|
|
# Комиссия платформы 10%
|
|
commission = transaction.amount * 0.10
|
|
freelancer_amount = transaction.amount - commission
|
|
|
|
transaction.status = "released"
|
|
await db.commit()
|
|
|
|
return {
|
|
"id": str(transaction.id),
|
|
"status": "released",
|
|
"freelancer_payout": float(freelancer_amount),
|
|
"platform_commission": float(commission),
|
|
}
|
|
|
|
|
|
@router.post("/dispute")
|
|
async def dispute_escrow(transaction_id: str, db: AsyncSession = Depends(get_db)):
|
|
"""Открыть спор по escrow."""
|
|
|
|
result = await db.execute(select(EscrowTransaction).where(EscrowTransaction.id == transaction_id))
|
|
transaction = result.scalar_one_or_none()
|
|
|
|
if not transaction:
|
|
raise HTTPException(status_code=404, detail="Транзакция не найдена")
|
|
|
|
transaction.status = "disputed"
|
|
await db.commit()
|
|
|
|
return {"status": "dispute_opened", "transaction_id": str(transaction.id)}
|