- Frontend: Next.js 14 with TypeScript - Backend: FastAPI with SQLAlchemy - Agent: Carmodoo sync agent - Deployment: Docker Compose based staging/production setup - Scripts: Automated deployment with rollback support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
186 lines
4.9 KiB
Python
186 lines
4.9 KiB
Python
from pydantic import BaseModel
|
|
from typing import Optional, List, Any
|
|
from datetime import datetime
|
|
from decimal import Decimal
|
|
|
|
|
|
# CarSpecification Schema
|
|
class CarSpecificationResponse(BaseModel):
|
|
id: int
|
|
car_id: int
|
|
manufacturer: Optional[str] = None
|
|
model_name: Optional[str] = None
|
|
grade: Optional[str] = None
|
|
model_year: Optional[str] = None
|
|
displacement: Optional[int] = None
|
|
fuel_type: Optional[str] = None
|
|
transmission: Optional[str] = None
|
|
drive_type: Optional[str] = None
|
|
max_power: Optional[str] = None
|
|
max_torque: Optional[str] = None
|
|
fuel_efficiency: Optional[str] = None
|
|
body_type: Optional[str] = None
|
|
door_count: Optional[int] = None
|
|
seating_capacity: Optional[int] = None
|
|
length: Optional[int] = None
|
|
width: Optional[int] = None
|
|
height: Optional[int] = None
|
|
wheelbase: Optional[int] = None
|
|
curb_weight: Optional[int] = None
|
|
safety_options: Optional[List[str]] = None
|
|
comfort_options: Optional[List[str]] = None
|
|
exterior_options: Optional[List[str]] = None
|
|
interior_options: Optional[List[str]] = None
|
|
raw_data: Optional[Any] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# CarMaker Schemas
|
|
class CarMakerCreate(BaseModel):
|
|
code: str
|
|
name: str
|
|
name_en: Optional[str] = None
|
|
|
|
|
|
class CarMakerResponse(BaseModel):
|
|
id: int
|
|
code: str
|
|
name: str
|
|
name_en: Optional[str] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# CarModel Schemas
|
|
class CarModelCreate(BaseModel):
|
|
code: str
|
|
maker_id: int
|
|
name: str
|
|
name_en: Optional[str] = None
|
|
|
|
|
|
class CarModelResponse(BaseModel):
|
|
id: int
|
|
code: str
|
|
maker_id: int
|
|
name: str
|
|
name_en: Optional[str] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# CarImage Schemas
|
|
class CarImageCreate(BaseModel):
|
|
url: Optional[str] = None
|
|
local_path: Optional[str] = None
|
|
is_main: bool = False
|
|
sort_order: int = 0
|
|
|
|
|
|
class CarImageResponse(BaseModel):
|
|
id: int
|
|
url: Optional[str] = None
|
|
local_path: Optional[str] = None
|
|
is_main: bool
|
|
sort_order: int
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# Car Schemas
|
|
class CarCreate(BaseModel):
|
|
source: str = "carmodoo"
|
|
source_id: str
|
|
source_key: Optional[str] = None
|
|
maker_code: Optional[str] = None
|
|
model_code: Optional[str] = None
|
|
car_name: Optional[str] = None
|
|
year: Optional[int] = None
|
|
month: Optional[int] = None
|
|
mileage: Optional[int] = None
|
|
price_krw: Optional[int] = None
|
|
price_usd: Optional[Decimal] = None
|
|
fuel: Optional[str] = None
|
|
transmission: Optional[str] = None
|
|
color: Optional[str] = None
|
|
displacement: Optional[int] = None
|
|
car_number: Optional[str] = None
|
|
seize_count: int = 0
|
|
collateral_count: int = 0
|
|
check_num: Optional[str] = None
|
|
dealer_name: Optional[str] = None
|
|
dealer_phone: Optional[str] = None
|
|
shop_name: Optional[str] = None
|
|
memo: Optional[str] = None
|
|
images: List[CarImageCreate] = []
|
|
options: List[str] = []
|
|
|
|
|
|
class CarUpdate(BaseModel):
|
|
car_name: Optional[str] = None
|
|
year: Optional[int] = None
|
|
month: Optional[int] = None
|
|
mileage: Optional[int] = None
|
|
price_krw: Optional[int] = None
|
|
margin_krw: Optional[int] = None
|
|
margin_mn: Optional[int] = None
|
|
price_usd: Optional[Decimal] = None
|
|
fuel: Optional[str] = None
|
|
transmission: Optional[str] = None
|
|
color: Optional[str] = None
|
|
status: Optional[str] = None
|
|
is_displayed: Optional[bool] = None
|
|
|
|
|
|
class CarResponse(BaseModel):
|
|
id: int
|
|
source: str
|
|
source_id: str
|
|
car_name: Optional[str] = None
|
|
year: Optional[int] = None
|
|
month: Optional[int] = None
|
|
mileage: Optional[int] = None
|
|
price_krw: Optional[int] = None
|
|
margin_krw: Optional[int] = 0
|
|
margin_mn: Optional[int] = 0
|
|
final_price_krw: Optional[int] = None # Computed: price_krw + margin_krw (for Korean users)
|
|
final_price_mn: Optional[int] = None # Computed: price_krw + margin_mn (for Mongolian users)
|
|
price_usd: Optional[Decimal] = None
|
|
is_displayed: bool = False
|
|
fuel: Optional[str] = None
|
|
transmission: Optional[str] = None
|
|
color: Optional[str] = None
|
|
displacement: Optional[int] = None
|
|
car_number: Optional[str] = None
|
|
seize_count: int
|
|
collateral_count: int
|
|
check_num: Optional[str] = None
|
|
dealer_name: Optional[str] = None
|
|
dealer_description: Optional[str] = None
|
|
dealer_description_en: Optional[str] = None
|
|
dealer_description_mn: Optional[str] = None
|
|
dealer_description_ru: Optional[str] = None
|
|
status: str
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
maker: Optional[CarMakerResponse] = None
|
|
model: Optional[CarModelResponse] = None
|
|
images: List[CarImageResponse] = []
|
|
specification: Optional[CarSpecificationResponse] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class CarListResponse(BaseModel):
|
|
total: int
|
|
page: int
|
|
page_size: int
|
|
cars: List[CarResponse]
|