🚀 MVP: FastAPI + React форма с SMS верификацией
✅ Инфраструктура: PostgreSQL, Redis, RabbitMQ, S3 ✅ Backend: SMS сервис + API endpoints ✅ Frontend: React форма (3 шага) + SMS верификация
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
"""
|
||||
API Routes
|
||||
"""
|
||||
|
||||
|
||||
51
backend/app/api/claims.py
Normal file
51
backend/app/api/claims.py
Normal file
@@ -0,0 +1,51 @@
|
||||
"""
|
||||
Claims API Routes - Обработка заявок
|
||||
"""
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from .models import ClaimCreateRequest, ClaimResponse
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
|
||||
router = APIRouter(prefix="/api/v1/claims", tags=["Claims"])
|
||||
|
||||
|
||||
@router.post("/create", response_model=ClaimResponse)
|
||||
async def create_claim(claim: ClaimCreateRequest):
|
||||
"""
|
||||
Создать новую заявку
|
||||
|
||||
Принимает данные формы и создает заявку в системе
|
||||
"""
|
||||
try:
|
||||
# Генерируем ID и номер заявки
|
||||
claim_id = str(uuid.uuid4())
|
||||
claim_number = f"ERV-{datetime.now().strftime('%Y%m%d')}-{claim_id[:8].upper()}"
|
||||
|
||||
# TODO: Сохранить в PostgreSQL
|
||||
# TODO: Отправить в очередь RabbitMQ для обработки
|
||||
# TODO: Интеграция с CRM
|
||||
|
||||
return ClaimResponse(
|
||||
success=True,
|
||||
claim_id=claim_id,
|
||||
claim_number=claim_number,
|
||||
message=f"Заявка {claim_number} успешно создана"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=f"Ошибка при создании заявки: {str(e)}"
|
||||
)
|
||||
|
||||
|
||||
@router.get("/{claim_id}")
|
||||
async def get_claim(claim_id: str):
|
||||
"""Получить информацию о заявке по ID"""
|
||||
# TODO: Получить из БД
|
||||
return {
|
||||
"claim_id": claim_id,
|
||||
"status": "processing",
|
||||
"message": "Заявка в обработке"
|
||||
}
|
||||
|
||||
64
backend/app/api/models.py
Normal file
64
backend/app/api/models.py
Normal file
@@ -0,0 +1,64 @@
|
||||
"""
|
||||
Pydantic модели для API
|
||||
"""
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
from typing import Optional, List
|
||||
from datetime import date
|
||||
|
||||
|
||||
class SMSSendRequest(BaseModel):
|
||||
"""Запрос на отправку SMS кода"""
|
||||
phone: str = Field(..., description="Номер телефона в формате +79001234567")
|
||||
|
||||
@field_validator('phone')
|
||||
@classmethod
|
||||
def validate_phone(cls, v: str) -> str:
|
||||
# Убираем все кроме цифр и +
|
||||
clean = ''.join(c for c in v if c.isdigit() or c == '+')
|
||||
if not clean.startswith('+'):
|
||||
clean = '+' + clean
|
||||
if len(clean) != 12: # +7 + 10 цифр
|
||||
raise ValueError('Неверный формат телефона')
|
||||
return clean
|
||||
|
||||
|
||||
class SMSVerifyRequest(BaseModel):
|
||||
"""Запрос на проверку SMS кода"""
|
||||
phone: str = Field(..., description="Номер телефона")
|
||||
code: str = Field(..., min_length=6, max_length=6, description="6-значный код")
|
||||
|
||||
|
||||
class ClaimCreateRequest(BaseModel):
|
||||
"""Запрос на создание заявки"""
|
||||
# Шаг 1: Основная информация
|
||||
phone: str
|
||||
email: Optional[str] = None
|
||||
inn: Optional[str] = None
|
||||
policy_number: str
|
||||
policy_series: Optional[str] = None
|
||||
|
||||
# Шаг 2: Данные о происшествии
|
||||
incident_date: Optional[str] = None
|
||||
incident_description: Optional[str] = None
|
||||
transport_type: Optional[str] = None # "air", "train", "bus", etc.
|
||||
|
||||
# Шаг 3: Данные для выплаты
|
||||
payment_method: str = "sbp" # "sbp", "card", "bank_transfer"
|
||||
bank_name: Optional[str] = None
|
||||
card_number: Optional[str] = None
|
||||
account_number: Optional[str] = None
|
||||
|
||||
# Файлы (UUID после загрузки)
|
||||
uploaded_files: Optional[List[str]] = []
|
||||
|
||||
# Метаданные
|
||||
source: str = "web_form"
|
||||
|
||||
|
||||
class ClaimResponse(BaseModel):
|
||||
"""Ответ после создания заявки"""
|
||||
success: bool
|
||||
claim_id: Optional[str] = None
|
||||
claim_number: Optional[str] = None
|
||||
message: str
|
||||
|
||||
53
backend/app/api/sms.py
Normal file
53
backend/app/api/sms.py
Normal file
@@ -0,0 +1,53 @@
|
||||
"""
|
||||
SMS API Routes
|
||||
"""
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from ..services.sms_service import sms_service
|
||||
from .models import SMSSendRequest, SMSVerifyRequest
|
||||
|
||||
router = APIRouter(prefix="/api/v1/sms", tags=["SMS"])
|
||||
|
||||
|
||||
@router.post("/send")
|
||||
async def send_sms_code(request: SMSSendRequest):
|
||||
"""
|
||||
Отправить SMS код верификации
|
||||
|
||||
- **phone**: Номер телефона в формате +79001234567
|
||||
"""
|
||||
code = await sms_service.send_verification_code(request.phone)
|
||||
|
||||
if code:
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Код отправлен на указанный номер",
|
||||
"debug_code": code if sms_service.enabled else None # Показываем код только в dev
|
||||
}
|
||||
else:
|
||||
raise HTTPException(
|
||||
status_code=429,
|
||||
detail="Слишком много запросов. Попробуйте через минуту."
|
||||
)
|
||||
|
||||
|
||||
@router.post("/verify")
|
||||
async def verify_sms_code(request: SMSVerifyRequest):
|
||||
"""
|
||||
Проверить SMS код
|
||||
|
||||
- **phone**: Номер телефона
|
||||
- **code**: 6-значный код из SMS
|
||||
"""
|
||||
is_valid = await sms_service.verify_code(request.phone, request.code)
|
||||
|
||||
if is_valid:
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Код подтвержден"
|
||||
}
|
||||
else:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="Неверный код или код истек"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user