Refactor code structure for improved readability and maintainability
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from datetime import UTC, datetime
|
||||
|
||||
from sqlalchemy import (
|
||||
Boolean,
|
||||
CheckConstraint,
|
||||
DateTime,
|
||||
ForeignKey,
|
||||
Integer,
|
||||
Numeric,
|
||||
String,
|
||||
Text,
|
||||
)
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
|
||||
|
||||
|
||||
class Base(DeclarativeBase):
|
||||
pass
|
||||
|
||||
|
||||
def uuid_pk() -> Mapped[uuid.UUID]:
|
||||
return mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
||||
|
||||
|
||||
def now() -> datetime:
|
||||
return datetime.now(UTC)
|
||||
|
||||
|
||||
class TimestampMixin:
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=now)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=now, onupdate=now)
|
||||
|
||||
|
||||
class Equipment(Base, TimestampMixin):
|
||||
__tablename__ = "logic_equipment"
|
||||
|
||||
id: Mapped[uuid.UUID] = uuid_pk()
|
||||
owner_user_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), index=True)
|
||||
name: Mapped[str] = mapped_column(String(160), index=True)
|
||||
description: Mapped[str | None] = mapped_column(Text)
|
||||
image_s3_url: Mapped[str | None] = mapped_column(Text)
|
||||
image_s3_key: Mapped[str | None] = mapped_column(Text)
|
||||
is_builtin: Mapped[bool] = mapped_column(Boolean, default=False, index=True)
|
||||
|
||||
workout_items: Mapped[list[WorkoutItem]] = relationship(back_populates="equipment")
|
||||
|
||||
|
||||
class Exercise(Base, TimestampMixin):
|
||||
__tablename__ = "logic_exercises"
|
||||
|
||||
id: Mapped[uuid.UUID] = uuid_pk()
|
||||
owner_user_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), index=True)
|
||||
equipment_id: Mapped[uuid.UUID | None] = mapped_column(ForeignKey("logic_equipment.id"))
|
||||
name: Mapped[str] = mapped_column(String(160), index=True)
|
||||
description: Mapped[str | None] = mapped_column(Text)
|
||||
image_s3_url: Mapped[str | None] = mapped_column(Text)
|
||||
image_s3_key: Mapped[str | None] = mapped_column(Text)
|
||||
is_builtin: Mapped[bool] = mapped_column(Boolean, default=False, index=True)
|
||||
default_calories_per_minute: Mapped[float | None] = mapped_column(Numeric(8, 2))
|
||||
|
||||
equipment: Mapped[Equipment | None] = relationship()
|
||||
workout_items: Mapped[list[WorkoutItem]] = relationship(back_populates="exercise")
|
||||
|
||||
|
||||
class Workout(Base, TimestampMixin):
|
||||
__tablename__ = "logic_workouts"
|
||||
|
||||
id: Mapped[uuid.UUID] = uuid_pk()
|
||||
user_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), 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)
|
||||
estimated_calories: Mapped[float] = mapped_column(Numeric(10, 2), default=0)
|
||||
|
||||
items: Mapped[list[WorkoutItem]] = relationship(
|
||||
back_populates="workout", cascade="all, delete-orphan", order_by="WorkoutItem.order_index"
|
||||
)
|
||||
|
||||
|
||||
class WorkoutItem(Base):
|
||||
__tablename__ = "logic_workout_items"
|
||||
__table_args__ = (
|
||||
CheckConstraint(
|
||||
"(exercise_id IS NOT NULL AND equipment_id IS NULL) OR "
|
||||
"(exercise_id IS NULL AND equipment_id IS NOT NULL)",
|
||||
name="ck_workout_item_exactly_one_entity",
|
||||
),
|
||||
)
|
||||
|
||||
id: Mapped[uuid.UUID] = uuid_pk()
|
||||
workout_id: Mapped[uuid.UUID] = mapped_column(
|
||||
ForeignKey("logic_workouts.id", ondelete="CASCADE")
|
||||
)
|
||||
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)
|
||||
planned_working_weight: Mapped[float | None] = mapped_column(Numeric(8, 2))
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=now)
|
||||
|
||||
workout: Mapped[Workout] = relationship(back_populates="items")
|
||||
exercise: Mapped[Exercise | None] = relationship(back_populates="workout_items")
|
||||
equipment: Mapped[Equipment | None] = relationship(back_populates="workout_items")
|
||||
sets: Mapped[list[WorkoutSet]] = relationship(
|
||||
back_populates="workout_item", cascade="all, delete-orphan", order_by="WorkoutSet.set_index"
|
||||
)
|
||||
|
||||
|
||||
class WorkoutSet(Base):
|
||||
__tablename__ = "logic_workout_sets"
|
||||
|
||||
id: Mapped[uuid.UUID] = uuid_pk()
|
||||
workout_item_id: Mapped[uuid.UUID] = mapped_column(
|
||||
ForeignKey("logic_workout_items.id", ondelete="CASCADE")
|
||||
)
|
||||
set_index: Mapped[int] = mapped_column(Integer)
|
||||
weight: Mapped[float] = mapped_column(Numeric(8, 2), default=0)
|
||||
reps: Mapped[int] = mapped_column(Integer, default=0)
|
||||
duration_seconds: Mapped[int | None] = mapped_column(Integer)
|
||||
calories: Mapped[float | None] = mapped_column(Numeric(8, 2))
|
||||
completed_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=now)
|
||||
|
||||
workout_item: Mapped[WorkoutItem] = relationship(back_populates="sets")
|
||||
Reference in New Issue
Block a user