fooder-api/fooder/domain/diary.py

120 lines
3.1 KiB
Python
Raw Normal View History

2023-04-01 16:19:12 +02:00
from sqlalchemy.orm import relationship, Mapped, mapped_column, joinedload
from sqlalchemy import ForeignKey, Integer, Date
from sqlalchemy import select
2023-04-02 15:31:38 +02:00
from sqlalchemy.sql.selectable import Select
2023-04-01 16:19:12 +02:00
from sqlalchemy.ext.asyncio import AsyncSession
2024-05-20 13:45:21 +02:00
import datetime
2023-04-01 16:19:12 +02:00
from typing import Optional
from .base import Base, CommonMixin
from .meal import Meal
2023-04-02 15:31:38 +02:00
from .entry import Entry
2023-04-01 16:19:12 +02:00
class Diary(Base, CommonMixin):
"""Diary represents user diary for given day"""
2023-04-03 13:46:03 +02:00
meals: Mapped[list[Meal]] = relationship(
lazy="selectin", order_by=Meal.order.desc()
)
2024-05-20 13:45:21 +02:00
date: Mapped[datetime.date] = mapped_column(Date)
2023-04-01 16:19:12 +02:00
user_id: Mapped[int] = mapped_column(Integer, ForeignKey("user.id"))
@property
def calories(self) -> float:
"""calories.
:rtype: float
"""
return sum(meal.calories for meal in self.meals)
@property
def protein(self) -> float:
"""protein.
:rtype: float
"""
return sum(meal.protein for meal in self.meals)
@property
def carb(self) -> float:
"""carb.
:rtype: float
"""
return sum(meal.carb for meal in self.meals)
@property
def fat(self) -> float:
"""fat.
:rtype: float
"""
return sum(meal.fat for meal in self.meals)
2023-07-30 20:18:42 +02:00
@property
def fiber(self) -> float:
"""fiber.
:rtype: float
"""
return sum(meal.fat for meal in self.meals)
2023-04-02 15:31:38 +02:00
@classmethod
def query(cls, user_id: int) -> Select:
"""get_all."""
query = (
select(cls)
.where(cls.user_id == user_id)
.options(
joinedload(cls.meals).joinedload(Meal.entries).joinedload(Entry.product)
)
)
return query
2023-04-01 16:19:12 +02:00
@classmethod
async def get_diary(
2024-05-20 13:45:21 +02:00
cls, session: AsyncSession, user_id: int, date: datetime.date
2023-04-01 16:19:12 +02:00
) -> "Optional[Diary]":
"""get_diary."""
2023-04-03 13:46:03 +02:00
query = cls.query(user_id).where(cls.date == date)
2023-04-01 16:19:12 +02:00
return await session.scalar(query)
@classmethod
2024-05-20 13:45:21 +02:00
async def create(
cls, session: AsyncSession, user_id: int, date: datetime.date
) -> "Diary":
2023-04-01 16:19:12 +02:00
diary = Diary(
date=date,
user_id=user_id,
)
session.add(diary)
try:
await session.flush()
except Exception:
raise RuntimeError()
2024-05-20 13:45:21 +02:00
db_diary = await cls.get_by_id(session, user_id, diary.id)
2023-04-01 16:19:12 +02:00
2024-05-20 13:45:21 +02:00
if not db_diary:
2023-04-01 16:19:12 +02:00
raise RuntimeError()
2024-05-20 13:45:21 +02:00
await Meal.create(session, db_diary.id)
return db_diary
2023-04-01 16:19:12 +02:00
@classmethod
async def get_by_id(
cls, session: AsyncSession, user_id: int, id: int
) -> "Optional[Diary]":
"""get_by_id."""
2023-04-03 13:46:03 +02:00
query = cls.query(user_id).where(cls.id == id)
2023-04-01 16:19:12 +02:00
return await session.scalar(query)
2023-04-03 13:46:03 +02:00
@classmethod
async def has_permission(cls, session: AsyncSession, user_id: int, id: int) -> bool:
"""has_permission."""
query = select(cls.id).where(cls.user_id == user_id).where(cls.id == id)
obj = await session.scalar(query)
return obj is not None