from sqlalchemy import Column, Integer, String, Float, ForeignKey, CheckConstraint, Index from sqlalchemy.orm import relationship from database import Base class Client(Base): __tablename__ = "clients" id = Column(Integer, primary_key=True, index=True) sync_id = Column(String, unique=True, nullable=False, index=True) full_name = Column(String, nullable=False) birth_date = Column(String) goal = Column(String, default="") notes = Column(String, default="") is_active = Column(Integer, default=1) created_at = Column(String) updated_at = Column(String) workouts = relationship("Workout", back_populates="client") body_metrics = relationship("BodyMetric", back_populates="client") class WorkoutType(Base): __tablename__ = "workout_types" id = Column(Integer, primary_key=True, index=True) sync_id = Column(String, unique=True, nullable=False, index=True) name = Column(String, unique=True, nullable=False) sort_order = Column(Integer, default=0) created_at = Column(String) exercises = relationship("Exercise", back_populates="workout_type") workouts = relationship("Workout", back_populates="workout_type") class Exercise(Base): __tablename__ = "exercises" id = Column(Integer, primary_key=True, index=True) sync_id = Column(String, unique=True, nullable=False, index=True) workout_type_id = Column(Integer, ForeignKey("workout_types.id", ondelete="SET NULL")) name = Column(String, nullable=False, index=True) created_at = Column(String) updated_at = Column(String) workout_type = relationship("WorkoutType", back_populates="exercises") workout_exercises = relationship("WorkoutExercise", back_populates="exercise") class Workout(Base): __tablename__ = "workouts" id = Column(Integer, primary_key=True, index=True) sync_id = Column(String, unique=True, nullable=False, index=True) client_id = Column(Integer, ForeignKey("clients.id", ondelete="SET NULL")) workout_type_id = Column(Integer, ForeignKey("workout_types.id", ondelete="SET NULL")) start_time = Column(String, nullable=False) end_time = Column(String) notes = Column(String, default="") synced = Column(Integer, default=0) created_at = Column(String) updated_at = Column(String) client = relationship("Client", back_populates="workouts") workout_type = relationship("WorkoutType", back_populates="workouts") workout_exercises = relationship("WorkoutExercise", back_populates="workout", cascade="all, delete-orphan") cardio_sessions = relationship("Cardio", back_populates="workout", cascade="all, delete-orphan") class WorkoutExercise(Base): __tablename__ = "workout_exercises" id = Column(Integer, primary_key=True, index=True) sync_id = Column(String, unique=True, nullable=False, index=True) workout_id = Column(Integer, ForeignKey("workouts.id", ondelete="CASCADE")) exercise_id = Column(Integer, ForeignKey("exercises.id", ondelete="SET NULL")) exercise_name = Column(String, nullable=False) sort_order = Column(Integer, default=0) created_at = Column(String) workout = relationship("Workout", back_populates="workout_exercises") exercise = relationship("Exercise", back_populates="workout_exercises") sets = relationship("Set", back_populates="workout_exercise", cascade="all, delete-orphan") class Set(Base): __tablename__ = "sets" id = Column(Integer, primary_key=True, index=True) sync_id = Column(String, unique=True, nullable=False, index=True) workout_exercise_id = Column(Integer, ForeignKey("workout_exercises.id", ondelete="CASCADE")) is_dropset = Column(Integer, default=0) weight = Column(Float) reps = Column(Integer) rating = Column(Integer) notes = Column(String, default="") sort_order = Column(Integer, default=0) timestamp = Column(String, nullable=False) created_at = Column(String) workout_exercise = relationship("WorkoutExercise", back_populates="sets") dropset_items = relationship("DropsetItem", back_populates="set", cascade="all, delete-orphan") __table_args__ = ( CheckConstraint( "(is_dropset = 0 AND weight IS NOT NULL AND reps IS NOT NULL) OR " "(is_dropset = 1 AND weight IS NULL AND reps IS NULL)", name="check_set_data" ), ) class DropsetItem(Base): __tablename__ = "dropset_items" id = Column(Integer, primary_key=True, index=True) set_id = Column(Integer, ForeignKey("sets.id", ondelete="CASCADE")) weight = Column(Float, nullable=False) reps = Column(Integer, nullable=False) sort_order = Column(Integer, default=0) set = relationship("Set", back_populates="dropset_items") class Cardio(Base): __tablename__ = "cardio" id = Column(Integer, primary_key=True, index=True) sync_id = Column(String, unique=True, nullable=False, index=True) workout_id = Column(Integer, ForeignKey("workouts.id", ondelete="CASCADE")) cardio_type = Column(String, nullable=False) purpose = Column(String, nullable=False) duration = Column(Integer) distance = Column(Float) speed = Column(Float) incline = Column(Float) resistance = Column(Integer) notes = Column(String, default="") sort_order = Column(Integer, default=0) created_at = Column(String) workout = relationship("Workout", back_populates="cardio_sessions") class MetricType(Base): __tablename__ = "metric_types" id = Column(Integer, primary_key=True, index=True) sync_id = Column(String, unique=True, nullable=False, index=True) name = Column(String, unique=True, nullable=False) unit = Column(String, default="см") category = Column(String, default="body") sort_order = Column(Integer, default=0) created_at = Column(String) metric_values = relationship("BodyMetricValue", back_populates="metric_type") class BodyMetric(Base): __tablename__ = "body_metrics" id = Column(Integer, primary_key=True, index=True) sync_id = Column(String, unique=True, nullable=False, index=True) client_id = Column(Integer, ForeignKey("clients.id", ondelete="SET NULL")) metric_date = Column(String, nullable=False) notes = Column(String, default="") created_at = Column(String) client = relationship("Client", back_populates="body_metrics") values = relationship("BodyMetricValue", back_populates="body_metric", cascade="all, delete-orphan") class BodyMetricValue(Base): __tablename__ = "body_metric_values" id = Column(Integer, primary_key=True, index=True) body_metric_id = Column(Integer, ForeignKey("body_metrics.id", ondelete="CASCADE")) metric_type_id = Column(Integer, ForeignKey("metric_types.id", ondelete="CASCADE")) value = Column(Float, nullable=False) body_metric = relationship("BodyMetric", back_populates="values") metric_type = relationship("MetricType", back_populates="metric_values")