241 lines
6.7 KiB
Python
241 lines
6.7 KiB
Python
"""
|
|
Pydantic Models for Shinkan Jinkendo API
|
|
|
|
Request/Response schemas for all endpoints
|
|
"""
|
|
from pydantic import BaseModel, EmailStr, Field
|
|
from typing import Optional, List
|
|
from datetime import date, time, datetime
|
|
|
|
# ============================================================================
|
|
# Auth & Profiles (von Mitai übernommen)
|
|
# ============================================================================
|
|
|
|
class LoginRequest(BaseModel):
|
|
email: EmailStr
|
|
password: str
|
|
|
|
class RegisterRequest(BaseModel):
|
|
email: EmailStr
|
|
password: str
|
|
name: Optional[str] = None
|
|
|
|
class PasswordResetRequest(BaseModel):
|
|
email: str
|
|
|
|
class PasswordResetConfirm(BaseModel):
|
|
token: str
|
|
new_password: str
|
|
|
|
class ProfileCreate(BaseModel):
|
|
name: str
|
|
email: Optional[str] = None
|
|
|
|
class ProfileUpdate(BaseModel):
|
|
name: Optional[str] = None
|
|
email: Optional[str] = None
|
|
|
|
class ProfileResponse(BaseModel):
|
|
id: int
|
|
email: str
|
|
name: Optional[str]
|
|
role: str
|
|
tier: str
|
|
email_verified: bool
|
|
created_at: datetime
|
|
|
|
# ============================================================================
|
|
# Clubs & Groups
|
|
# ============================================================================
|
|
|
|
class ClubCreate(BaseModel):
|
|
name: str
|
|
abbreviation: Optional[str] = None
|
|
description: Optional[str] = None
|
|
|
|
class ClubResponse(BaseModel):
|
|
id: int
|
|
name: str
|
|
abbreviation: Optional[str]
|
|
description: Optional[str]
|
|
status: str
|
|
created_at: datetime
|
|
|
|
class TrainingGroupCreate(BaseModel):
|
|
club_id: int
|
|
division_id: Optional[int] = None
|
|
name: str
|
|
focus: Optional[str] = None
|
|
level: Optional[str] = None
|
|
age_group: Optional[str] = None
|
|
weekday: Optional[str] = None
|
|
time_start: Optional[time] = None
|
|
time_end: Optional[time] = None
|
|
location: Optional[str] = None
|
|
trainer_id: Optional[int] = None
|
|
co_trainer_ids: Optional[List[int]] = []
|
|
|
|
class TrainingGroupResponse(BaseModel):
|
|
id: int
|
|
club_id: int
|
|
name: str
|
|
focus: Optional[str]
|
|
level: Optional[str]
|
|
age_group: Optional[str]
|
|
weekday: Optional[str]
|
|
time_start: Optional[time]
|
|
time_end: Optional[time]
|
|
location: Optional[str]
|
|
trainer_id: Optional[int]
|
|
status: str
|
|
created_at: datetime
|
|
|
|
# ============================================================================
|
|
# Skills & Methods
|
|
# ============================================================================
|
|
|
|
class SkillCreate(BaseModel):
|
|
name: str
|
|
category: Optional[str] = None
|
|
description: Optional[str] = None
|
|
importance: Optional[int] = Field(None, ge=1, le=5)
|
|
keywords: Optional[List[str]] = []
|
|
|
|
class SkillResponse(BaseModel):
|
|
id: int
|
|
name: str
|
|
category: Optional[str]
|
|
description: Optional[str]
|
|
importance: Optional[int]
|
|
keywords: Optional[List[str]]
|
|
status: str
|
|
created_at: datetime
|
|
|
|
class MethodCreate(BaseModel):
|
|
name: str
|
|
abbreviation: Optional[str] = None
|
|
category: Optional[str] = None
|
|
description: Optional[str] = None
|
|
typical_duration: Optional[int] = None
|
|
typical_group_size: Optional[str] = None
|
|
related_skills: Optional[List[int]] = []
|
|
keywords: Optional[List[str]] = []
|
|
|
|
class MethodResponse(BaseModel):
|
|
id: int
|
|
name: str
|
|
abbreviation: Optional[str]
|
|
category: Optional[str]
|
|
description: Optional[str]
|
|
typical_duration: Optional[int]
|
|
typical_group_size: Optional[str]
|
|
related_skills: Optional[List[int]]
|
|
keywords: Optional[List[str]]
|
|
status: str
|
|
created_at: datetime
|
|
|
|
# ============================================================================
|
|
# Exercises (Kernobjekt)
|
|
# ============================================================================
|
|
|
|
class ExerciseCreate(BaseModel):
|
|
title: str
|
|
summary: Optional[str] = None
|
|
goal: str
|
|
execution: str
|
|
preparation: Optional[str] = None
|
|
trainer_notes: Optional[str] = None
|
|
equipment: Optional[List[str]] = []
|
|
duration_min: Optional[int] = None
|
|
duration_max: Optional[int] = None
|
|
group_size_min: Optional[int] = None
|
|
group_size_max: Optional[int] = None
|
|
age_groups: Optional[List[str]] = []
|
|
focus_area: Optional[str] = None
|
|
secondary_areas: Optional[List[str]] = []
|
|
training_character: Optional[str] = None
|
|
primary_method_id: Optional[int] = None
|
|
secondary_method_ids: Optional[List[int]] = []
|
|
visibility: Optional[str] = "private"
|
|
club_id: Optional[int] = None
|
|
|
|
class ExerciseResponse(BaseModel):
|
|
id: int
|
|
title: str
|
|
summary: Optional[str]
|
|
goal: str
|
|
execution: str
|
|
preparation: Optional[str]
|
|
trainer_notes: Optional[str]
|
|
equipment: Optional[List[str]]
|
|
duration_min: Optional[int]
|
|
duration_max: Optional[int]
|
|
group_size_min: Optional[int]
|
|
group_size_max: Optional[int]
|
|
age_groups: Optional[List[str]]
|
|
focus_area: Optional[str]
|
|
secondary_areas: Optional[List[str]]
|
|
training_character: Optional[str]
|
|
primary_method_id: Optional[int]
|
|
secondary_method_ids: Optional[List[int]]
|
|
visibility: str
|
|
status: str
|
|
created_by: int
|
|
club_id: Optional[int]
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
class ExerciseSkillCreate(BaseModel):
|
|
exercise_id: int
|
|
skill_id: int
|
|
is_primary: bool = False
|
|
intensity: Optional[int] = Field(None, ge=1, le=5)
|
|
development_contribution: Optional[str] = None
|
|
required_level: Optional[int] = None
|
|
target_level: Optional[int] = None
|
|
|
|
# ============================================================================
|
|
# Training Planning
|
|
# ============================================================================
|
|
|
|
class TrainingUnitCreate(BaseModel):
|
|
group_id: int
|
|
date: date
|
|
time_start: Optional[time] = None
|
|
time_end: Optional[time] = None
|
|
derived_from_template_id: Optional[int] = None
|
|
derived_from_unit_id: Optional[int] = None
|
|
title: Optional[str] = None
|
|
goal: Optional[str] = None
|
|
focus_areas: Optional[List[str]] = []
|
|
|
|
class TrainingUnitResponse(BaseModel):
|
|
id: int
|
|
group_id: int
|
|
date: date
|
|
time_start: Optional[time]
|
|
time_end: Optional[time]
|
|
title: Optional[str]
|
|
goal: Optional[str]
|
|
focus_areas: Optional[List[str]]
|
|
completion_status: str
|
|
created_by: int
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
# ============================================================================
|
|
# Import
|
|
# ============================================================================
|
|
|
|
class WikiImportRequest(BaseModel):
|
|
import_type: str # skill, method, exercise
|
|
wiki_url: Optional[str] = None
|
|
dry_run: bool = False
|
|
|
|
class WikiImportResponse(BaseModel):
|
|
import_status: str
|
|
items_total: int
|
|
items_imported: int
|
|
items_failed: int
|
|
error_log: Optional[List[str]]
|