All checks were successful
continuous-integration/drone/push Build is passing
146 lines
7.0 KiB
Python
146 lines
7.0 KiB
Python
import uuid
|
||
|
||
from sqlalchemy import Boolean, Column, Date, Float, Integer, String, Text, ForeignKey
|
||
from sqlalchemy.dialects.postgresql import UUID
|
||
from sqlalchemy.sql import func
|
||
from sqlalchemy.sql.expression import text
|
||
from sqlalchemy.sql.sqltypes import TIMESTAMP
|
||
|
||
from shared.database import BaseModel
|
||
|
||
|
||
class FoodItem(BaseModel):
|
||
"""Модель для хранения информации о продуктах питания"""
|
||
__tablename__ = "food_items"
|
||
|
||
uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, unique=True, index=True)
|
||
|
||
# Основная информация о продукте
|
||
fatsecret_id = Column(String(50), unique=True, index=True, nullable=True) # ID продукта в FatSecret
|
||
name = Column(String(255), nullable=False)
|
||
brand = Column(String(255), nullable=True)
|
||
description = Column(Text, nullable=True)
|
||
food_type = Column(String(50), nullable=True) # generic, branded, etc.
|
||
serving_size = Column(String(100), nullable=True) # e.g. "1 cup" or "100g"
|
||
serving_weight_grams = Column(Float, nullable=True)
|
||
|
||
# Пищевая ценность на порцию
|
||
calories = Column(Float, nullable=True) # kcal
|
||
protein_grams = Column(Float, nullable=True)
|
||
fat_grams = Column(Float, nullable=True)
|
||
carbs_grams = Column(Float, nullable=True)
|
||
fiber_grams = Column(Float, nullable=True)
|
||
sugar_grams = Column(Float, nullable=True)
|
||
sodium_mg = Column(Float, nullable=True)
|
||
cholesterol_mg = Column(Float, nullable=True)
|
||
|
||
# Дополнительная информация
|
||
ingredients = Column(Text, nullable=True)
|
||
is_verified = Column(Boolean, default=False) # Проверенные данные или пользовательские
|
||
created_at = Column(TIMESTAMP(timezone=True), nullable=False, server_default=func.now())
|
||
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
|
||
|
||
def __repr__(self):
|
||
return f"<FoodItem {self.name}>"
|
||
|
||
|
||
class UserNutritionEntry(BaseModel):
|
||
"""Модель для хранения записей пользователя о потреблении пищи"""
|
||
__tablename__ = "user_nutrition_entries"
|
||
|
||
uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, unique=True, index=True)
|
||
user_id = Column(Integer, nullable=False, index=True) # Связь с таблицей пользователей
|
||
|
||
# Информация о приеме пищи
|
||
entry_date = Column(Date, nullable=False, index=True)
|
||
meal_type = Column(String(50), nullable=False) # breakfast, lunch, dinner, snack
|
||
|
||
food_item_id = Column(Integer, ForeignKey("food_items.id"), nullable=True)
|
||
custom_food_name = Column(String(255), nullable=True) # Если продукт не из базы
|
||
|
||
# Количество
|
||
quantity = Column(Float, nullable=False, default=1.0)
|
||
unit = Column(String(50), nullable=True) # g, ml, oz, piece, etc.
|
||
|
||
# Рассчитанная пищевая ценность для данного количества
|
||
calories = Column(Float, nullable=True)
|
||
protein_grams = Column(Float, nullable=True)
|
||
fat_grams = Column(Float, nullable=True)
|
||
carbs_grams = Column(Float, nullable=True)
|
||
|
||
# Метаданные
|
||
notes = Column(Text, nullable=True)
|
||
created_at = Column(TIMESTAMP(timezone=True), nullable=False, server_default=func.now())
|
||
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
|
||
|
||
def __repr__(self):
|
||
return f"<UserNutritionEntry user_id={self.user_id} date={self.entry_date} meal={self.meal_type}>"
|
||
|
||
|
||
class WaterIntake(BaseModel):
|
||
"""Модель для отслеживания потребления воды"""
|
||
__tablename__ = "water_intake"
|
||
|
||
uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, unique=True, index=True)
|
||
user_id = Column(Integer, nullable=False, index=True) # Связь с таблицей пользователей
|
||
|
||
entry_date = Column(Date, nullable=False, index=True)
|
||
amount_ml = Column(Integer, nullable=False) # Количество в миллилитрах
|
||
entry_time = Column(TIMESTAMP(timezone=True), nullable=False, server_default=func.now())
|
||
|
||
notes = Column(Text, nullable=True)
|
||
|
||
def __repr__(self):
|
||
return f"<WaterIntake user_id={self.user_id} date={self.entry_date} amount={self.amount_ml}ml>"
|
||
|
||
|
||
class UserActivityEntry(BaseModel):
|
||
"""Модель для отслеживания физической активности"""
|
||
__tablename__ = "user_activity_entries"
|
||
|
||
uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, unique=True, index=True)
|
||
user_id = Column(Integer, nullable=False, index=True) # Связь с таблицей пользователей
|
||
|
||
entry_date = Column(Date, nullable=False, index=True)
|
||
activity_type = Column(String(100), nullable=False) # walking, running, yoga, etc.
|
||
|
||
duration_minutes = Column(Integer, nullable=False)
|
||
calories_burned = Column(Float, nullable=True) # Расчетное количество сожженных калорий
|
||
|
||
# Дополнительные параметры активности
|
||
distance_km = Column(Float, nullable=True) # Для активностей с расстоянием
|
||
steps = Column(Integer, nullable=True) # Для ходьбы
|
||
intensity = Column(String(20), nullable=True) # low, medium, high
|
||
|
||
notes = Column(Text, nullable=True)
|
||
created_at = Column(TIMESTAMP(timezone=True), nullable=False, server_default=func.now())
|
||
|
||
def __repr__(self):
|
||
return f"<UserActivityEntry user_id={self.user_id} date={self.entry_date} activity={self.activity_type}>"
|
||
|
||
|
||
class NutritionGoal(BaseModel):
|
||
"""Модель для хранения целей пользователя по питанию и активности"""
|
||
__tablename__ = "nutrition_goals"
|
||
|
||
user_id = Column(Integer, nullable=False, index=True, unique=True) # Связь с таблицей пользователей
|
||
|
||
# Цели по калориям и макронутриентам
|
||
daily_calorie_goal = Column(Integer, nullable=True)
|
||
protein_goal_grams = Column(Integer, nullable=True)
|
||
fat_goal_grams = Column(Integer, nullable=True)
|
||
carbs_goal_grams = Column(Integer, nullable=True)
|
||
|
||
# Цели по воде и активности
|
||
water_goal_ml = Column(Integer, nullable=True, default=2000) # Стандартно 2 литра
|
||
activity_goal_minutes = Column(Integer, nullable=True, default=30) # Минимум 30 минут активности
|
||
|
||
# Цель по весу и предпочтения
|
||
weight_goal_kg = Column(Float, nullable=True)
|
||
goal_type = Column(String(50), nullable=True) # lose_weight, maintain, gain_weight, health
|
||
|
||
created_at = Column(TIMESTAMP(timezone=True), nullable=False, server_default=func.now())
|
||
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
|
||
|
||
def __repr__(self):
|
||
return f"<NutritionGoal user_id={self.user_id} calories={self.daily_calorie_goal}>" |