feat: Implement active workout flow with status management
- Added `status`, `total_sets`, and `total_volume` fields to the Workout model. - Introduced `source_kind`, `title_snapshot`, and `image_s3_url_snapshot` fields to the WorkoutItem model. - Created endpoints for managing active workouts, including finishing and discarding workouts. - Updated workout creation to ensure only one active workout exists per user. - Implemented batch addition of workout sets and updates to workout set details. - Enhanced database schema with Alembic migrations to support new fields and constraints. - Added validation to ensure at least one field is provided for workout set updates. - Updated calorie estimation logic to reflect new workout set structure.
This commit is contained in:
@@ -67,12 +67,21 @@ class Exercise(Base, TimestampMixin):
|
||||
|
||||
class Workout(Base, TimestampMixin):
|
||||
__tablename__ = "logic_workouts"
|
||||
__table_args__ = (
|
||||
CheckConstraint(
|
||||
"status IN ('active', 'finished', 'discarded')",
|
||||
name="ck_workout_status",
|
||||
),
|
||||
)
|
||||
|
||||
id: Mapped[uuid.UUID] = uuid_pk()
|
||||
user_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), index=True)
|
||||
status: Mapped[str] = mapped_column(String(20), default="active", index=True)
|
||||
started_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=now)
|
||||
finished_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
notes: Mapped[str | None] = mapped_column(Text)
|
||||
total_sets: Mapped[int] = mapped_column(Integer, default=0)
|
||||
total_volume: Mapped[float] = mapped_column(Numeric(12, 2), default=0)
|
||||
estimated_calories: Mapped[float] = mapped_column(Numeric(10, 2), default=0)
|
||||
|
||||
items: Mapped[list[WorkoutItem]] = relationship(
|
||||
@@ -88,12 +97,19 @@ class WorkoutItem(Base):
|
||||
"(exercise_id IS NULL AND equipment_id IS NOT NULL)",
|
||||
name="ck_workout_item_exactly_one_entity",
|
||||
),
|
||||
CheckConstraint(
|
||||
"source_kind IN ('exercise', 'equipment')",
|
||||
name="ck_workout_item_source_kind",
|
||||
),
|
||||
)
|
||||
|
||||
id: Mapped[uuid.UUID] = uuid_pk()
|
||||
workout_id: Mapped[uuid.UUID] = mapped_column(
|
||||
ForeignKey("logic_workouts.id", ondelete="CASCADE")
|
||||
)
|
||||
source_kind: Mapped[str] = mapped_column(String(20))
|
||||
title_snapshot: Mapped[str] = mapped_column(String(160))
|
||||
image_s3_url_snapshot: Mapped[str | None] = mapped_column(Text)
|
||||
exercise_id: Mapped[uuid.UUID | None] = mapped_column(ForeignKey("logic_exercises.id"))
|
||||
equipment_id: Mapped[uuid.UUID | None] = mapped_column(ForeignKey("logic_equipment.id"))
|
||||
order_index: Mapped[int] = mapped_column(Integer, default=0)
|
||||
|
||||
Reference in New Issue
Block a user