feat: Freelancer Match — AI-матчинг, escrow, milestones, portfolio, skill-tests, verification
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
"""Pydantic схемы для валидации запросов/ответов."""
|
||||
|
||||
from app.schemas.user import UserCreate, UserLogin, UserProfileUpdate, FreelancerProfileCreate
|
||||
from app.schemas.project import ProjectCreate, ProjectUpdate, ProjectResponse
|
||||
from app.schemas.proposal import ProposalCreate, ProposalResponse
|
||||
from app.schemas.ai_match import AIMatchRequest, AIMatchResponse
|
||||
from app.schemas.escrow import EscrowCreate, EscrowRelease
|
||||
from app.schemas.auth import TokenPair
|
||||
|
||||
__all__ = [
|
||||
"UserCreate", "UserLogin", "UserProfileUpdate", "FreelancerProfileCreate",
|
||||
"ProjectCreate", "ProjectUpdate", "ProjectResponse",
|
||||
"ProposalCreate", "ProposalResponse",
|
||||
"AIMatchRequest", "AIMatchResponse",
|
||||
"EscrowCreate", "EscrowRelease",
|
||||
"TokenPair",
|
||||
]
|
||||
@@ -0,0 +1,17 @@
|
||||
"""Схемы AI-матчинга."""
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class AIMatchRequest(BaseModel):
|
||||
project_id: str = Field(..., description="ID проекта")
|
||||
limit: int = Field(default=10, ge=1, le=50)
|
||||
min_score: float | None = Field(default=None, ge=0.0, le=1.0)
|
||||
|
||||
|
||||
class AIMatchResponse(BaseModel):
|
||||
freelancer_id: str
|
||||
name: str
|
||||
skills_matched: list[str]
|
||||
match_score: float
|
||||
reasons: list[str]
|
||||
@@ -0,0 +1,8 @@
|
||||
"""Схемы авторизации."""
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class TokenPair(BaseModel):
|
||||
access_token: str
|
||||
refresh_token: str
|
||||
@@ -0,0 +1,14 @@
|
||||
"""Схемы escrow-транзакций."""
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class EscrowCreate(BaseModel):
|
||||
project_id: str = Field(..., description="ID проекта")
|
||||
client_id: str = Field(..., description="ID клиента")
|
||||
freelancer_id: str = Field(..., description="ID фрилансера")
|
||||
amount: float = Field(..., gt=0, description="Сумма в рублях")
|
||||
|
||||
|
||||
class EscrowRelease(BaseModel):
|
||||
transaction_id: str = Field(..., description="ID транзакции")
|
||||
@@ -0,0 +1,36 @@
|
||||
"""Схемы проектов."""
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class ProjectCreate(BaseModel):
|
||||
title: str = Field(..., min_length=5, max_length=255)
|
||||
description: str = Field(..., min_length=20)
|
||||
category: str | None = None
|
||||
required_skills: list[str] = []
|
||||
budget_min: float | None = None
|
||||
budget_max: float | None = None
|
||||
deadline: str | None = None # ISO format
|
||||
|
||||
|
||||
class ProjectUpdate(BaseModel):
|
||||
title: str | None = None
|
||||
description: str | None = None
|
||||
status: str | None = None
|
||||
budget_min: float | None = None
|
||||
budget_max: float | None = None
|
||||
deadline: str | None = None
|
||||
|
||||
|
||||
class ProjectResponse(BaseModel):
|
||||
id: str
|
||||
title: str
|
||||
description: str
|
||||
category: str | None
|
||||
required_skills: list[str]
|
||||
budget_min: float | None
|
||||
budget_max: float | None
|
||||
status: str
|
||||
deadline: str | None
|
||||
created_at: str
|
||||
updated_at: str
|
||||
@@ -0,0 +1,20 @@
|
||||
"""Схемы заявок."""
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class ProposalCreate(BaseModel):
|
||||
cover_letter: str | None = None
|
||||
proposed_price: float | None = None
|
||||
estimated_days: int | None = None
|
||||
|
||||
|
||||
class ProposalResponse(BaseModel):
|
||||
id: str
|
||||
project_id: str
|
||||
freelancer_id: str
|
||||
cover_letter: str | None
|
||||
proposed_price: float | None
|
||||
estimated_days: int | None
|
||||
status: str
|
||||
created_at: str
|
||||
@@ -0,0 +1,20 @@
|
||||
"""Схемы отзывов и рейтингов."""
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class ReviewCreate(BaseModel):
|
||||
project_id: str = Field(..., description="ID проекта")
|
||||
reviewee_id: str = Field(..., description="ID того кого оценивают")
|
||||
rating: int = Field(..., ge=1, le=5)
|
||||
comment: str | None = Field(default=None, max_length=2000)
|
||||
|
||||
|
||||
class ReviewResponse(BaseModel):
|
||||
id: str
|
||||
project_id: str
|
||||
reviewer_name: str
|
||||
reviewee_name: str
|
||||
rating: int
|
||||
comment: str | None
|
||||
created_at: str
|
||||
@@ -0,0 +1,28 @@
|
||||
"""Схемы пользователей."""
|
||||
|
||||
from pydantic import BaseModel, EmailStr
|
||||
|
||||
|
||||
class UserCreate(BaseModel):
|
||||
email: EmailStr
|
||||
password: str # min 12 chars
|
||||
role: str = "freelancer" # client | freelancer | both
|
||||
full_name: str | None = None
|
||||
|
||||
|
||||
class UserLogin(BaseModel):
|
||||
email: EmailStr
|
||||
password: str
|
||||
|
||||
|
||||
class UserProfileUpdate(BaseModel):
|
||||
full_name: str | None = None
|
||||
avatar_url: str | None = None
|
||||
|
||||
|
||||
class FreelancerProfileCreate(BaseModel):
|
||||
bio: str | None = None
|
||||
skills: list[str] = []
|
||||
hourly_rate: float | None = None
|
||||
experience_years: int | None = None
|
||||
languages: list[str] = []
|
||||
Reference in New Issue
Block a user