Completed and abandoned habits were both lumped under a single terminal state, making it impossible to tell "finished successfully" apart from "gave up" when reviewing habit history.
64 lines
1.5 KiB
Python
64 lines
1.5 KiB
Python
from datetime import datetime, time
|
|
|
|
from pydantic import BaseModel, ConfigDict, field_validator
|
|
|
|
from app.models.habit import ALL_WEEKDAYS_MASK, HabitStatus, HabitType
|
|
|
|
|
|
class HabitBase(BaseModel):
|
|
name: str
|
|
habit_type: HabitType
|
|
weekdays_mask: int = ALL_WEEKDAYS_MASK
|
|
condition_text: str | None = None
|
|
reminder_time: time | None = None
|
|
|
|
@field_validator("name")
|
|
@classmethod
|
|
def name_not_blank(cls, v: str) -> str:
|
|
v = v.strip()
|
|
if not v:
|
|
raise ValueError("습관 이름을 입력해주세요")
|
|
return v
|
|
|
|
@field_validator("condition_text")
|
|
@classmethod
|
|
def blank_condition_to_none(cls, v: str | None) -> str | None:
|
|
if v is None:
|
|
return None
|
|
v = v.strip()
|
|
return v or None
|
|
|
|
@field_validator("weekdays_mask")
|
|
@classmethod
|
|
def mask_in_range(cls, v: int) -> int:
|
|
if not (1 <= v <= ALL_WEEKDAYS_MASK):
|
|
raise ValueError("요일을 최소 하루 이상 선택해주세요")
|
|
return v
|
|
|
|
|
|
class HabitCreate(HabitBase):
|
|
pass
|
|
|
|
|
|
class HabitUpdate(HabitBase):
|
|
pass
|
|
|
|
|
|
class HabitOut(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
name: str
|
|
habit_type: HabitType
|
|
status: HabitStatus
|
|
weekdays_mask: int
|
|
condition_text: str | None
|
|
reminder_time: time | None
|
|
created_at: datetime
|
|
completed_at: datetime | None
|
|
abandoned_at: datetime | None
|
|
|
|
|
|
class HabitReorderRequest(BaseModel):
|
|
habit_ids: list[int]
|