Skip to content

Commit

Permalink
refactor: remove all sqlalchemy's relationships (see #11 and #20 issu…
Browse files Browse the repository at this point in the history
…es on GH)
  • Loading branch information
Makcal committed May 23, 2024
1 parent 55b2d2c commit e6fa5bb
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 100 deletions.
62 changes: 34 additions & 28 deletions src/api/routes/bot.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from datetime import datetime
from typing import Annotated, Sequence
from typing import Annotated, Sequence, Iterable

from fastapi import APIRouter, Body
from sqlalchemy import select, exists, delete, update
Expand Down Expand Up @@ -73,12 +73,13 @@ async def create_user(user: CreateUserBody, db: DB_SESSION_DEPENDENCY) -> int:

@bot_router.post("/room/create", response_description="The id of created room")
async def create_room(user: USER_DEPENDENCY, room: CreateRoomBody, db: DB_SESSION_DEPENDENCY) -> int:
if user.room is not None:
if user.room_id is not None:
raise UserHasRoomException()

room = Room(name=room.name)
user.room = room
db.add(room)
await db.flush()
user.room_id = room.id
await db.commit()

return room.id
Expand Down Expand Up @@ -141,7 +142,8 @@ async def accept_invitation(user: USER_DEPENDENCY, invitation: AcceptInvitationB
async def create_order(
room: ROOM_DEPENDENCY, order: CreateOrderBody, db: DB_SESSION_DEPENDENCY, settings: SETTINGS_DEPENDENCY
) -> int:
number_of_orders = len(room.orders)
# number_of_orders = len(room.orders)
number_of_orders: int = await db.scalar(select(count()).where(Order.room_id == room.id))
if number_of_orders >= settings.MAX_ORDERS:
raise TooManyOrdersException()

Expand All @@ -155,11 +157,13 @@ async def create_order(
raise SpecifiedUserNotInRoomException(user_id)

order = Order(room_id=room.id)
db.add(order)
await db.flush()
for i, user in enumerate(order_list):
executor = TaskExecutor(user_id=user.id, order_number=i)
executor.order = order
executor.order_id = order.id
db.add(executor)

db.add(order)
await db.commit()

return order.id
Expand All @@ -169,7 +173,8 @@ async def create_order(
async def create_task(
room: ROOM_DEPENDENCY, task: CreateTaskBody, db: DB_SESSION_DEPENDENCY, settings: SETTINGS_DEPENDENCY
) -> int:
number_of_tasks = len(room.tasks)
# number_of_tasks = len(room.tasks)
number_of_tasks: int = await db.scalar(select(count()).where(Task.room_id == room.id))
if number_of_tasks >= settings.MAX_TASKS:
raise TooManyTasksException()

Expand Down Expand Up @@ -204,12 +209,17 @@ async def modify_task(room: ROOM_DEPENDENCY, task: ModifyTaskBody, db: DB_SESSIO
@bot_router.post("/room/daily_info", response_description="Statuses of the tasks of the room")
async def get_daily_info(room: ROOM_DEPENDENCY, db: DB_SESSION_DEPENDENCY) -> DailyInfoResponse:
response = DailyInfoResponse(tasks=[])
task: Task
for task in room.tasks:
tasks: Iterable[Task] = await db.scalars(select(Task).where(Task.room_id == room.id))
for task in tasks:
if task.is_inactive():
continue

executors = task.order.executors
# executors = task.order.executors
executors: Sequence[TaskExecutor] = (
await db.scalars(
select(TaskExecutor).order_by(TaskExecutor.order_number).where(TaskExecutor.order_id == task.order_id)
)
).all()
i = (datetime.now() - task.start_date).days % len(executors)

today_executor: TaskExecutor
Expand All @@ -234,8 +244,10 @@ async def get_incoming_invitations(user: USER_DEPENDENCY, db: DB_SESSION_DEPENDE
if user.alias is None:
return response

i: Invitation
for i in (await db.execute(select(Invitation).where(Invitation.addressee_alias == user.alias))).unique().scalars():
invitations: Iterable[Invitation] = await db.scalars(
select(Invitation).where(Invitation.addressee_alias == user.alias)
)
for i in invitations:
if i.expiration_date <= datetime.now():
await db.delete(i)
continue
Expand All @@ -256,7 +268,7 @@ async def get_incoming_invitations(user: USER_DEPENDENCY, db: DB_SESSION_DEPENDE

@bot_router.post("/room/info", response_description="Info about the user's room")
async def get_room_info(room: ROOM_DEPENDENCY, db: DB_SESSION_DEPENDENCY) -> RoomInfoResponse:
user_ids = [id_ for id_ in (await db.execute(select(User.id).where(User.room_id == room.id))).unique().scalars()]
user_ids = [id_ for id_ in await db.scalars(select(User.id).where(User.room_id == room.id))]
users = [await db.get_one(User, id_) for id_ in user_ids]
return RoomInfoResponse(
id=room.id, name=room.name, users=[UserInfo(alias=user.alias, fullname=user.fullname) for user in users]
Expand All @@ -277,10 +289,10 @@ async def leave_room(user: USER_DEPENDENCY, room: ROOM_DEPENDENCY, db: DB_SESSIO


@bot_router.post("/task/list", response_description="The full list of a room's tasks")
async def get_tasks(room: ROOM_DEPENDENCY) -> TaskListResponse:
async def get_tasks(room: ROOM_DEPENDENCY, db: DB_SESSION_DEPENDENCY) -> TaskListResponse:
response = TaskListResponse(tasks=[])
task: Task
for task in room.tasks:
tasks: Iterable[Task] = await db.scalars(select(Task).where(Task.room_id == room.id))
for task in tasks:
inactive = task.is_inactive()
response.tasks.append(TaskInfo(id=task.id, name=task.name, inactive=inactive))

Expand Down Expand Up @@ -346,18 +358,12 @@ async def reject_invitation(user: USER_DEPENDENCY, invitation: RejectInvitationB
async def get_order_info(room: ROOM_DEPENDENCY, order: OrderInfoBody, db: DB_SESSION_DEPENDENCY) -> OrderInfoResponse:
order = await check_order_exists(order.id, room.id, db)

users: Sequence[User] = (
(
await db.execute(
select(User)
.select_from(TaskExecutor)
.join(User)
.order_by(TaskExecutor.order_number)
.where(TaskExecutor.order_id == order.id)
)
)
.unique()
.scalars()
users: Iterable[User] = await db.scalars(
select(User)
.select_from(TaskExecutor)
.join(User)
.order_by(TaskExecutor.order_number)
.where(TaskExecutor.order_id == order.id)
)

return OrderInfoResponse(users=[UserInfo(alias=u.alias, fullname=u.fullname) for u in users])
Expand Down
6 changes: 3 additions & 3 deletions src/api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ async def check_room_exists(room_id: int, db: AsyncSession) -> Room:
return room


async def room_dependency(user: USER_DEPENDENCY) -> Room:
if user.room is None:
async def room_dependency(user: USER_DEPENDENCY, db: DB_SESSION_DEPENDENCY) -> Room:
if user.room_id is None:
raise UserWithoutRoomException()
# noinspection PyTypeChecker
return user.room
return await db.get_one(Room, user.room_id)


ROOM_DEPENDENCY = Annotated[Room, Depends(room_dependency)]
Expand Down
13 changes: 6 additions & 7 deletions src/models/sql/invitation.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import typing
from datetime import datetime, timedelta

from sqlalchemy import ForeignKey, BigInteger, Column
from sqlmodel import SQLModel, Field, Relationship
from sqlmodel import SQLModel, Field

from src.config import get_settings

if typing.TYPE_CHECKING:
from src.models.sql.user import User
from src.models.sql.room import Room
# if typing.TYPE_CHECKING:
# from src.models.sql.user import User
# from src.models.sql.room import Room


class Invitation(SQLModel, table=True):
Expand All @@ -24,8 +23,8 @@ class Invitation(SQLModel, table=True):
default_factory=lambda: datetime.now() + timedelta(days=get_settings().INVITATION_LIFESPAN_DAYS)
)

sender: "User" = Relationship(sa_relationship_kwargs={"lazy": "joined"})
room: "Room" = Relationship(back_populates="invitations", sa_relationship_kwargs={"lazy": "joined"})
# sender: "User" = Relationship(sa_relationship_kwargs={"lazy": "joined"})
# room: "Room" = Relationship(back_populates="invitations", sa_relationship_kwargs={"lazy": "joined"})

def __init__(
self,
Expand Down
26 changes: 12 additions & 14 deletions src/models/sql/order.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import typing

from sqlalchemy import ForeignKey
from sqlmodel import SQLModel, Field, Relationship
from sqlmodel import SQLModel, Field

if typing.TYPE_CHECKING:
from src.models.sql.user import User
from src.models.sql.task import Task
from src.models.sql.task_executor import TaskExecutor
from src.models.sql.room import Room
# if typing.TYPE_CHECKING:
# from src.models.sql.user import User
# from src.models.sql.task import Task
# from src.models.sql.task_executor import TaskExecutor
# from src.models.sql.room import Room


class Order(SQLModel, table=True):
Expand All @@ -16,12 +14,12 @@ class Order(SQLModel, table=True):
id: int = Field(primary_key=True)
room_id: int = Field(sa_column_args=(ForeignKey("rooms.id", onupdate="CASCADE", ondelete="CASCADE"),))

room: "Room" = Relationship(back_populates="orders", sa_relationship_kwargs={"lazy": "joined"})
users: list["User"] = Relationship(
back_populates="orders", sa_relationship_kwargs={"lazy": "joined", "secondary": "executors", "viewonly": True}
)
executors: list["TaskExecutor"] = Relationship(back_populates="order", sa_relationship_kwargs={"lazy": "joined"})
tasks: list["Task"] = Relationship(back_populates="order", sa_relationship_kwargs={"lazy": "joined"})
# room: "Room" = Relationship(back_populates="orders", sa_relationship_kwargs={"lazy": "joined"})
# users: list["User"] = Relationship(
# back_populates="orders", sa_relationship_kwargs={"lazy": "joined", "secondary": "executors", "viewonly": True}
# )
# executors: list["TaskExecutor"] = Relationship(back_populates="order", sa_relationship_kwargs={"lazy": "joined"})
# tasks: list["Task"] = Relationship(back_populates="order", sa_relationship_kwargs={"lazy": "joined"})

def __init__(self, id_: int = None, room_id: int = None):
super().__init__(id=id_, room_id=room_id)
Expand Down
22 changes: 10 additions & 12 deletions src/models/sql/room.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import typing
from sqlmodel import SQLModel, Field

from sqlmodel import SQLModel, Relationship, Field

if typing.TYPE_CHECKING:
from src.models.sql.user import User
from src.models.sql.invitation import Invitation
from src.models.sql.task import Task
from src.models.sql.order import Order
# if typing.TYPE_CHECKING:
# from src.models.sql.user import User
# from src.models.sql.invitation import Invitation
# from src.models.sql.task import Task
# from src.models.sql.order import Order


class Room(SQLModel, table=True):
Expand All @@ -15,10 +13,10 @@ class Room(SQLModel, table=True):
id: int = Field(primary_key=True)
name: str

users: list["User"] = Relationship(back_populates="room", sa_relationship_kwargs={"lazy": "joined"})
invitations: list["Invitation"] = Relationship(back_populates="room", sa_relationship_kwargs={"lazy": "joined"})
tasks: list["Task"] = Relationship(sa_relationship_kwargs={"lazy": "joined"})
orders: list["Order"] = Relationship(back_populates="room", sa_relationship_kwargs={"lazy": "joined"})
# users: list["User"] = Relationship(back_populates="room", sa_relationship_kwargs={"lazy": "joined"})
# invitations: list["Invitation"] = Relationship(back_populates="room", sa_relationship_kwargs={"lazy": "joined"})
# tasks: list["Task"] = Relationship(sa_relationship_kwargs={"lazy": "joined"})
# orders: list["Order"] = Relationship(back_populates="room", sa_relationship_kwargs={"lazy": "joined"})

def __init__(self, id_: int = None, name: str = None):
super().__init__(id=id_, name=name)
Expand Down
9 changes: 4 additions & 5 deletions src/models/sql/task.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import typing
from datetime import datetime
from typing import Optional

from sqlalchemy import ForeignKey
from sqlmodel import SQLModel, Field, Relationship
from sqlmodel import SQLModel, Field

if typing.TYPE_CHECKING:
from src.models.sql.order import Order
# if typing.TYPE_CHECKING:
# from src.models.sql.order import Order


class Task(SQLModel, table=True):
Expand All @@ -20,7 +19,7 @@ class Task(SQLModel, table=True):
period: int # in days
order_id: Optional[int] = Field(sa_column_args=(ForeignKey("orders.id", onupdate="CASCADE", ondelete="SET NULL"),))

order: Optional["Order"] = Relationship(back_populates="tasks", sa_relationship_kwargs={"lazy": "joined"})
# order: Optional["Order"] = Relationship(back_populates="tasks", sa_relationship_kwargs={"lazy": "joined"})

def __init__(
self,
Expand Down
14 changes: 6 additions & 8 deletions src/models/sql/task_executor.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import typing

from sqlalchemy import UniqueConstraint, ForeignKey, Column, BigInteger
from sqlmodel import SQLModel, Field, Relationship
from sqlmodel import SQLModel, Field

if typing.TYPE_CHECKING:
from src.models.sql.user import User
from src.models.sql.order import Order
# if typing.TYPE_CHECKING:
# from src.models.sql.user import User
# from src.models.sql.order import Order


class TaskExecutor(SQLModel, table=True):
Expand All @@ -27,8 +25,8 @@ class TaskExecutor(SQLModel, table=True):
)
order_number: int = Field(primary_key=True, sa_column_kwargs={"autoincrement": False})

user: "User" = Relationship(back_populates="executors", sa_relationship_kwargs={"lazy": "joined"})
order: "Order" = Relationship(back_populates="executors", sa_relationship_kwargs={"lazy": "joined"})
# user: "User" = Relationship(back_populates="executors", sa_relationship_kwargs={"lazy": "joined"})
# order: "Order" = Relationship(back_populates="executors", sa_relationship_kwargs={"lazy": "joined"})

def __init__(
self,
Expand Down
28 changes: 13 additions & 15 deletions src/models/sql/user.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import typing
from datetime import datetime
from typing import Optional

from sqlalchemy import ForeignKey, func, BigInteger, Column
from sqlmodel import SQLModel, Field, Relationship
from sqlmodel import SQLModel, Field

if typing.TYPE_CHECKING:
from src.models.sql.room import Room

# from src.models.sql.invitation import Invitation
from src.models.sql.order import Order
from src.models.sql.task_executor import TaskExecutor
# if typing.TYPE_CHECKING:
# from src.models.sql.room import Room
#
# # from src.models.sql.invitation import Invitation
# from src.models.sql.order import Order
# from src.models.sql.task_executor import TaskExecutor


class User(SQLModel, table=True):
Expand All @@ -23,12 +21,12 @@ class User(SQLModel, table=True):
room_id: int | None = Field(sa_column_args=(ForeignKey("rooms.id", onupdate="CASCADE", ondelete="SET NULL"),))
register_datetime: datetime | None = Field(sa_column_kwargs={"server_default": func.now()})

room: Optional["Room"] = Relationship(back_populates="users", sa_relationship_kwargs={"lazy": "joined"})
# invitations: list["Invitation"] = Relationship(sa_relationship_kwargs={"lazy": "joined"})
orders: list["Order"] = Relationship(
back_populates="users", sa_relationship_kwargs={"lazy": "joined", "secondary": "executors", "viewonly": True}
)
executors: list["TaskExecutor"] = Relationship(back_populates="user", sa_relationship_kwargs={"lazy": "joined"})
# room: Optional["Room"] = Relationship(back_populates="users", sa_relationship_kwargs={"lazy": "joined"})
# # invitations: list["Invitation"] = Relationship(sa_relationship_kwargs={"lazy": "joined"})
# orders: list["Order"] = Relationship(
# back_populates="users", sa_relationship_kwargs={"lazy": "joined", "secondary": "executors", "viewonly": True}
# )
# executors: list["TaskExecutor"] = Relationship(back_populates="user", sa_relationship_kwargs={"lazy": "joined"})

def __init__(
self,
Expand Down
Loading

0 comments on commit e6fa5bb

Please sign in to comment.