348 lines
8.2 KiB
Python
348 lines
8.2 KiB
Python
from pydantic import BaseModel, Field
|
|
from typing import Optional, List, Dict, Any
|
|
|
|
|
|
# ============================================================
|
|
# AUTH / USERS
|
|
# ============================================================
|
|
class UserCreate(BaseModel):
|
|
username: str
|
|
password: str
|
|
display_name: Optional[str] = ""
|
|
role: Optional[str] = "personal"
|
|
|
|
|
|
class UserLogin(BaseModel):
|
|
username: str
|
|
password: str
|
|
|
|
|
|
class UserOut(BaseModel):
|
|
id: int
|
|
username: str
|
|
display_name: str
|
|
role: str
|
|
created_at: str
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class Token(BaseModel):
|
|
access_token: str
|
|
token_type: str = "bearer"
|
|
user: UserOut
|
|
|
|
|
|
# ============================================================
|
|
# WORKOUT TYPES
|
|
# ============================================================
|
|
class WorkoutTypeBase(BaseModel):
|
|
name: str
|
|
sort_order: Optional[int] = 0
|
|
|
|
|
|
class WorkoutTypeCreate(WorkoutTypeBase):
|
|
sync_id: Optional[str] = None
|
|
|
|
|
|
class WorkoutTypeOut(WorkoutTypeBase):
|
|
id: int
|
|
sync_id: str
|
|
created_at: str
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# ============================================================
|
|
# METRIC TYPES
|
|
# ============================================================
|
|
class MetricTypeBase(BaseModel):
|
|
name: str
|
|
unit: Optional[str] = "см"
|
|
category: Optional[str] = "body"
|
|
sort_order: Optional[int] = 0
|
|
|
|
|
|
class MetricTypeCreate(MetricTypeBase):
|
|
sync_id: Optional[str] = None
|
|
|
|
|
|
class MetricTypeOut(MetricTypeBase):
|
|
id: int
|
|
sync_id: str
|
|
created_at: str
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# ============================================================
|
|
# CLIENTS
|
|
# ============================================================
|
|
class ClientBase(BaseModel):
|
|
full_name: str
|
|
birth_date: Optional[str] = None
|
|
goal: Optional[str] = ""
|
|
notes: Optional[str] = ""
|
|
color: Optional[str] = None
|
|
is_active: Optional[int] = 1
|
|
|
|
|
|
class ClientCreate(ClientBase):
|
|
sync_id: Optional[str] = None
|
|
|
|
|
|
class ClientUpdate(BaseModel):
|
|
full_name: Optional[str] = None
|
|
birth_date: Optional[str] = None
|
|
goal: Optional[str] = None
|
|
notes: Optional[str] = None
|
|
color: Optional[str] = None
|
|
is_active: Optional[int] = None
|
|
|
|
|
|
class ClientOut(ClientBase):
|
|
id: int
|
|
sync_id: str
|
|
owner_id: Optional[int] = None
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# ============================================================
|
|
# EXERCISES
|
|
# ============================================================
|
|
class ExerciseBase(BaseModel):
|
|
name: str
|
|
workout_type_id: Optional[int] = None
|
|
|
|
|
|
class ExerciseCreate(ExerciseBase):
|
|
sync_id: Optional[str] = None
|
|
|
|
|
|
class ExerciseUpdate(BaseModel):
|
|
name: Optional[str] = None
|
|
workout_type_id: Optional[int] = None
|
|
|
|
|
|
class ExerciseOut(ExerciseBase):
|
|
id: int
|
|
sync_id: str
|
|
owner_id: Optional[int] = None
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# ============================================================
|
|
# DROPSET ITEMS
|
|
# ============================================================
|
|
class DropsetItemBase(BaseModel):
|
|
weight: float = Field(gt=0)
|
|
reps: int = Field(gt=0)
|
|
sort_order: int = 0
|
|
|
|
|
|
class DropsetItemCreate(DropsetItemBase):
|
|
pass
|
|
|
|
|
|
class DropsetItemOut(DropsetItemBase):
|
|
id: int
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# ============================================================
|
|
# SETS
|
|
# ============================================================
|
|
class SetBase(BaseModel):
|
|
is_dropset: int = 0
|
|
weight: Optional[float] = None
|
|
reps: Optional[int] = None
|
|
rating: Optional[int] = Field(None, ge=1, le=5)
|
|
notes: Optional[str] = ""
|
|
sort_order: int = 0
|
|
timestamp: str
|
|
|
|
|
|
class SetCreate(SetBase):
|
|
sync_id: Optional[str] = None
|
|
dropset_items: List[DropsetItemCreate] = Field(default_factory=list)
|
|
|
|
|
|
class SetOut(SetBase):
|
|
id: int
|
|
sync_id: str
|
|
created_at: str
|
|
dropset_items: List[DropsetItemOut] = Field(default_factory=list)
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# ============================================================
|
|
# WORKOUT EXERCISES
|
|
# ============================================================
|
|
class WorkoutExerciseBase(BaseModel):
|
|
exercise_name: str
|
|
exercise_id: Optional[int] = None
|
|
exercise_sync_id: Optional[str] = None
|
|
sort_order: int = 0
|
|
|
|
|
|
class WorkoutExerciseCreate(WorkoutExerciseBase):
|
|
sync_id: Optional[str] = None
|
|
sets: List[SetCreate] = Field(default_factory=list)
|
|
|
|
|
|
class WorkoutExerciseOut(WorkoutExerciseBase):
|
|
id: int
|
|
sync_id: str
|
|
created_at: str
|
|
sets: List[SetOut] = Field(default_factory=list)
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# ============================================================
|
|
# CARDIO
|
|
# ============================================================
|
|
class CardioBase(BaseModel):
|
|
cardio_type: str
|
|
purpose: str
|
|
duration: Optional[int] = None
|
|
distance: Optional[float] = None
|
|
speed: Optional[float] = None
|
|
incline: Optional[float] = None
|
|
resistance: Optional[int] = None
|
|
notes: Optional[str] = ""
|
|
sort_order: int = 0
|
|
|
|
|
|
class CardioCreate(CardioBase):
|
|
sync_id: Optional[str] = None
|
|
|
|
|
|
class CardioOut(CardioBase):
|
|
id: int
|
|
sync_id: str
|
|
created_at: str
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# ============================================================
|
|
# WORKOUTS
|
|
# ============================================================
|
|
class WorkoutBase(BaseModel):
|
|
start_time: str
|
|
end_time: Optional[str] = None
|
|
notes: Optional[str] = ""
|
|
workout_type_id: Optional[int] = None
|
|
|
|
|
|
class WorkoutCreate(WorkoutBase):
|
|
sync_id: Optional[str] = None
|
|
client_id: Optional[int] = None
|
|
client_sync_id: Optional[str] = None
|
|
workout_exercises: List[WorkoutExerciseCreate] = Field(default_factory=list)
|
|
cardio_sessions: List[CardioCreate] = Field(default_factory=list)
|
|
|
|
|
|
class WorkoutUpdate(BaseModel):
|
|
workout_type_id: Optional[int] = None
|
|
end_time: Optional[str] = None
|
|
notes: Optional[str] = None
|
|
synced: Optional[int] = None
|
|
|
|
|
|
class WorkoutOut(WorkoutBase):
|
|
id: int
|
|
sync_id: str
|
|
owner_id: Optional[int] = None
|
|
client_id: Optional[int] = None
|
|
synced: int
|
|
created_at: str
|
|
updated_at: str
|
|
workout_exercises: List[WorkoutExerciseOut] = Field(default_factory=list)
|
|
cardio_sessions: List[CardioOut] = Field(default_factory=list)
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# ============================================================
|
|
# BODY METRIC VALUES
|
|
# ============================================================
|
|
class BodyMetricValueBase(BaseModel):
|
|
value: float
|
|
|
|
|
|
class BodyMetricValueCreate(BodyMetricValueBase):
|
|
metric_type_id: Optional[int] = None
|
|
metric_type_sync_id: Optional[str] = None
|
|
|
|
|
|
class BodyMetricValueOut(BodyMetricValueBase):
|
|
id: int
|
|
metric_type_id: int
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# ============================================================
|
|
# BODY METRICS
|
|
# ============================================================
|
|
class BodyMetricBase(BaseModel):
|
|
metric_date: str
|
|
notes: Optional[str] = ""
|
|
|
|
|
|
class BodyMetricCreate(BodyMetricBase):
|
|
sync_id: Optional[str] = None
|
|
client_id: Optional[int] = None
|
|
client_sync_id: Optional[str] = None
|
|
values: List[BodyMetricValueCreate] = Field(default_factory=list)
|
|
|
|
|
|
class BodyMetricOut(BodyMetricBase):
|
|
id: int
|
|
sync_id: str
|
|
owner_id: Optional[int] = None
|
|
client_id: Optional[int] = None
|
|
created_at: str
|
|
values: List[BodyMetricValueOut] = Field(default_factory=list)
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# ============================================================
|
|
# SYNC
|
|
# ============================================================
|
|
class SyncPayload(BaseModel):
|
|
clients: List[ClientCreate] = Field(default_factory=list)
|
|
exercises: List[ExerciseCreate] = Field(default_factory=list)
|
|
workouts: List[WorkoutCreate] = Field(default_factory=list)
|
|
body_metrics: List[BodyMetricCreate] = Field(default_factory=list)
|
|
|
|
|
|
class SyncResponse(BaseModel):
|
|
status: str
|
|
created: Dict[str, int]
|
|
updated: Dict[str, int]
|
|
warnings: List[str] = Field(default_factory=list)
|