mirror of
https://github.com/koloideal/DutyLog.git
synced 2026-06-10 18:35:29 +03:00
update
This commit is contained in:
@@ -20,10 +20,10 @@ class HoursTransactionsDAO:
|
||||
)
|
||||
return list(result.scalars().all())
|
||||
|
||||
async def get_by_user_id(self, user_id: int) -> list[HoursTransaction]:
|
||||
async def get_by_resident_id(self, resident_id: int) -> list[HoursTransaction]:
|
||||
result = await self.session.execute(
|
||||
select(HoursTransaction)
|
||||
.where(HoursTransaction.user_id == user_id)
|
||||
.where(HoursTransaction.resident_id == resident_id)
|
||||
.order_by(HoursTransaction.created_at.desc())
|
||||
)
|
||||
return list(result.scalars().all())
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
from sqlalchemy import select, update, delete
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from dutylog.infrastructure.database.models.resident import Resident
|
||||
|
||||
|
||||
class ResidentsDAO:
|
||||
def __init__(self, session: AsyncSession):
|
||||
self.session = session
|
||||
|
||||
async def get_by_id(self, resident_id: int) -> Resident | None:
|
||||
result = await self.session.execute(
|
||||
select(Resident).where(Resident.id == resident_id)
|
||||
)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
async def get_by_user_id(self, user_id: int) -> Resident | None:
|
||||
result = await self.session.execute(
|
||||
select(Resident).where(Resident.user_entity == user_id)
|
||||
)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
async def get_by_room(self, room_id: int) -> list[Resident]:
|
||||
result = await self.session.execute(
|
||||
select(Resident).where(Resident.room == room_id)
|
||||
)
|
||||
return list(result.scalars().all())
|
||||
|
||||
async def get_available(self) -> list[Resident]:
|
||||
result = await self.session.execute(
|
||||
select(Resident).where(Resident.is_busy == False)
|
||||
)
|
||||
return list(result.scalars().all())
|
||||
|
||||
async def get_all(self) -> list[Resident]:
|
||||
result = await self.session.execute(select(Resident))
|
||||
return list(result.scalars().all())
|
||||
|
||||
async def create(self, resident: Resident) -> Resident:
|
||||
self.session.add(resident)
|
||||
await self.session.commit()
|
||||
await self.session.refresh(resident)
|
||||
return resident
|
||||
|
||||
async def update(self, resident_id: int, **kwargs) -> Resident | None:
|
||||
await self.session.execute(
|
||||
update(Resident).where(Resident.id == resident_id).values(**kwargs)
|
||||
)
|
||||
await self.session.commit()
|
||||
return await self.get_by_id(resident_id)
|
||||
|
||||
async def delete(self, resident_id: int) -> None:
|
||||
await self.session.execute(
|
||||
delete(Resident).where(Resident.id == resident_id)
|
||||
)
|
||||
await self.session.commit()
|
||||
@@ -0,0 +1,44 @@
|
||||
from sqlalchemy import select, update, delete
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from dutylog.infrastructure.database.models.room import Room
|
||||
|
||||
|
||||
class RoomsDAO:
|
||||
def __init__(self, session: AsyncSession):
|
||||
self.session = session
|
||||
|
||||
async def get_by_id(self, room_id: int) -> Room | None:
|
||||
result = await self.session.execute(
|
||||
select(Room).where(Room.id == room_id)
|
||||
)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
async def get_by_number(self, number: int) -> Room | None:
|
||||
result = await self.session.execute(
|
||||
select(Room).where(Room.number == number)
|
||||
)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
async def get_all(self) -> list[Room]:
|
||||
result = await self.session.execute(select(Room))
|
||||
return list(result.scalars().all())
|
||||
|
||||
async def create(self, room: Room) -> Room:
|
||||
self.session.add(room)
|
||||
await self.session.commit()
|
||||
await self.session.refresh(room)
|
||||
return room
|
||||
|
||||
async def update(self, room_id: int, **kwargs) -> Room | None:
|
||||
await self.session.execute(
|
||||
update(Room).where(Room.id == room_id).values(**kwargs)
|
||||
)
|
||||
await self.session.commit()
|
||||
return await self.get_by_id(room_id)
|
||||
|
||||
async def delete(self, room_id: int) -> None:
|
||||
await self.session.execute(
|
||||
delete(Room).where(Room.id == room_id)
|
||||
)
|
||||
await self.session.commit()
|
||||
@@ -1,5 +1,7 @@
|
||||
from dutylog.infrastructure.database.models.base import Base
|
||||
from dutylog.infrastructure.database.models.user import User
|
||||
from dutylog.infrastructure.database.models.hours_transaction import HoursTransaction
|
||||
from dutylog.infrastructure.database.models.room import Room
|
||||
from dutylog.infrastructure.database.models.resident import Resident
|
||||
|
||||
__all__ = ["Base", "User", "HoursTransaction"]
|
||||
__all__ = ["Base", "User", "HoursTransaction", "Room", "Resident"]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
|
||||
from sqlalchemy import BigInteger, Integer, String, DateTime, ForeignKey
|
||||
@@ -17,7 +17,7 @@ class HoursTransaction(Base):
|
||||
__tablename__ = "hours_transactions"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
user_id: Mapped[int] = mapped_column(BigInteger, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
|
||||
resident_id: Mapped[int] = mapped_column(Integer, ForeignKey("residents.id", ondelete="CASCADE"), nullable=False)
|
||||
transaction_type: Mapped[str] = mapped_column(String(50), nullable=False)
|
||||
amount: Mapped[int] = mapped_column(Integer, nullable=False)
|
||||
admin_id: Mapped[int] = mapped_column(BigInteger, ForeignKey("users.id", ondelete="SET NULL"), nullable=True)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import BigInteger, Boolean, Integer, String, DateTime, ForeignKey
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from dutylog.infrastructure.database.models.base import Base
|
||||
from dutylog.infrastructure.utils.datetime import msk_now
|
||||
|
||||
|
||||
class Resident(Base):
|
||||
__tablename__ = "residents"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
real_name: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
room: Mapped[int] = mapped_column(Integer, ForeignKey("rooms.id", ondelete="CASCADE"), nullable=False)
|
||||
user_entity: Mapped[int | None] = mapped_column(BigInteger, ForeignKey("users.id", ondelete="SET NULL"), nullable=True, unique=True)
|
||||
is_busy: Mapped[bool] = mapped_column(Boolean, default=False, server_default="false")
|
||||
active_hours: Mapped[int] = mapped_column(Integer, default=0, server_default="0")
|
||||
inactive_hours: Mapped[int] = mapped_column(Integer, default=0, server_default="0")
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=msk_now)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=msk_now, onupdate=msk_now)
|
||||
@@ -0,0 +1,11 @@
|
||||
from sqlalchemy import Integer
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from dutylog.infrastructure.database.models.base import Base
|
||||
|
||||
|
||||
class Room(Base):
|
||||
__tablename__ = "rooms"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
number: Mapped[int] = mapped_column(Integer, nullable=False, unique=True)
|
||||
@@ -1,6 +1,6 @@
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import BigInteger, Boolean, Integer, String, DateTime
|
||||
from sqlalchemy import BigInteger, Boolean, String, DateTime
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from dutylog.infrastructure.database.models.base import Base
|
||||
@@ -15,7 +15,5 @@ class User(Base):
|
||||
first_name: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
last_name: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
is_admin: Mapped[bool] = mapped_column(Boolean, default=False, server_default="false")
|
||||
active_hours: Mapped[int] = mapped_column(Integer, default=0, server_default="0")
|
||||
inactive_hours: Mapped[int] = mapped_column(Integer, default=0, server_default="0")
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=msk_now)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=msk_now, onupdate=msk_now)
|
||||
|
||||
@@ -1,72 +1,72 @@
|
||||
from dutylog.infrastructure.database.dao.hours_transactions_dao import HoursTransactionsDAO
|
||||
from dutylog.infrastructure.database.dao.users_dao import UsersDAO
|
||||
from dutylog.infrastructure.database.dao.residents_dao import ResidentsDAO
|
||||
from dutylog.infrastructure.database.models.hours_transaction import HoursTransaction, TransactionType
|
||||
from dutylog.infrastructure.database.models.user import User
|
||||
from dutylog.infrastructure.database.models.resident import Resident
|
||||
|
||||
|
||||
class HoursTransactionsRepository:
|
||||
def __init__(
|
||||
self,
|
||||
transactions_dao: HoursTransactionsDAO,
|
||||
users_dao: UsersDAO,
|
||||
residents_dao: ResidentsDAO,
|
||||
):
|
||||
self.transactions_dao = transactions_dao
|
||||
self.users_dao = users_dao
|
||||
self.residents_dao = residents_dao
|
||||
|
||||
async def add_hours(
|
||||
self,
|
||||
user_id: int,
|
||||
resident_id: int,
|
||||
amount: int,
|
||||
admin_id: int | None = None,
|
||||
is_active: bool = True,
|
||||
) -> tuple[HoursTransaction, User | None]:
|
||||
) -> tuple[HoursTransaction, Resident | None]:
|
||||
transaction = HoursTransaction(
|
||||
user_id=user_id,
|
||||
resident_id=resident_id,
|
||||
transaction_type=TransactionType.INCREASE.value,
|
||||
amount=amount,
|
||||
admin_id=admin_id,
|
||||
)
|
||||
transaction = await self.transactions_dao.create(transaction)
|
||||
|
||||
user = await self.users_dao.get_by_id(user_id)
|
||||
if user:
|
||||
resident = await self.residents_dao.get_by_id(resident_id)
|
||||
if resident:
|
||||
if is_active:
|
||||
new_hours = user.active_hours + amount
|
||||
user = await self.users_dao.update(user_id, active_hours=new_hours)
|
||||
new_hours = resident.active_hours + amount
|
||||
resident = await self.residents_dao.update(resident_id, active_hours=new_hours)
|
||||
else:
|
||||
new_hours = user.inactive_hours + amount
|
||||
user = await self.users_dao.update(user_id, inactive_hours=new_hours)
|
||||
new_hours = resident.inactive_hours + amount
|
||||
resident = await self.residents_dao.update(resident_id, inactive_hours=new_hours)
|
||||
|
||||
return transaction, user
|
||||
return transaction, resident
|
||||
|
||||
async def remove_hours(
|
||||
self,
|
||||
user_id: int,
|
||||
resident_id: int,
|
||||
amount: int,
|
||||
admin_id: int | None = None,
|
||||
is_active: bool = True,
|
||||
) -> tuple[HoursTransaction, User | None]:
|
||||
) -> tuple[HoursTransaction, Resident | None]:
|
||||
transaction = HoursTransaction(
|
||||
user_id=user_id,
|
||||
resident_id=resident_id,
|
||||
transaction_type=TransactionType.DECREASE.value,
|
||||
amount=amount,
|
||||
admin_id=admin_id,
|
||||
)
|
||||
transaction = await self.transactions_dao.create(transaction)
|
||||
|
||||
user = await self.users_dao.get_by_id(user_id)
|
||||
if user:
|
||||
resident = await self.residents_dao.get_by_id(resident_id)
|
||||
if resident:
|
||||
if is_active:
|
||||
new_hours = max(0, user.active_hours - amount)
|
||||
user = await self.users_dao.update(user_id, active_hours=new_hours)
|
||||
new_hours = max(0, resident.active_hours - amount)
|
||||
resident = await self.residents_dao.update(resident_id, active_hours=new_hours)
|
||||
else:
|
||||
new_hours = max(0, user.inactive_hours - amount)
|
||||
user = await self.users_dao.update(user_id, inactive_hours=new_hours)
|
||||
new_hours = max(0, resident.inactive_hours - amount)
|
||||
resident = await self.residents_dao.update(resident_id, inactive_hours=new_hours)
|
||||
|
||||
return transaction, user
|
||||
return transaction, resident
|
||||
|
||||
async def get_user_history(self, user_id: int) -> list[HoursTransaction]:
|
||||
return await self.transactions_dao.get_by_user_id(user_id)
|
||||
async def get_resident_history(self, resident_id: int) -> list[HoursTransaction]:
|
||||
return await self.transactions_dao.get_by_resident_id(resident_id)
|
||||
|
||||
async def get_all_transactions(self) -> list[HoursTransaction]:
|
||||
return await self.transactions_dao.get_all()
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
from dutylog.infrastructure.database.dao.residents_dao import ResidentsDAO
|
||||
from dutylog.infrastructure.database.models.resident import Resident
|
||||
|
||||
|
||||
class ResidentsRepository:
|
||||
def __init__(self, residents_dao: ResidentsDAO):
|
||||
self.residents_dao = residents_dao
|
||||
|
||||
async def create_resident(
|
||||
self,
|
||||
room_id: int,
|
||||
real_name: str | None = None,
|
||||
) -> Resident:
|
||||
resident = Resident(
|
||||
room=room_id,
|
||||
real_name=real_name,
|
||||
)
|
||||
return await self.residents_dao.create(resident)
|
||||
|
||||
async def bind_user_to_resident(self, resident_id: int, user_id: int) -> Resident | None:
|
||||
return await self.residents_dao.update(
|
||||
resident_id,
|
||||
user_entity=user_id,
|
||||
is_busy=True,
|
||||
)
|
||||
|
||||
async def unbind_user_from_resident(self, resident_id: int) -> Resident | None:
|
||||
return await self.residents_dao.update(
|
||||
resident_id,
|
||||
user_entity=None,
|
||||
is_busy=False,
|
||||
)
|
||||
|
||||
async def update_resident_info(
|
||||
self,
|
||||
resident_id: int,
|
||||
real_name: str | None = None,
|
||||
) -> Resident | None:
|
||||
return await self.residents_dao.update(
|
||||
resident_id,
|
||||
real_name=real_name,
|
||||
)
|
||||
|
||||
async def add_active_hours(self, resident_id: int, hours: int) -> Resident | None:
|
||||
resident = await self.residents_dao.get_by_id(resident_id)
|
||||
if resident:
|
||||
new_hours = resident.active_hours + hours
|
||||
return await self.residents_dao.update(resident_id, active_hours=new_hours)
|
||||
return None
|
||||
|
||||
async def add_inactive_hours(self, resident_id: int, hours: int) -> Resident | None:
|
||||
resident = await self.residents_dao.get_by_id(resident_id)
|
||||
if resident:
|
||||
new_hours = resident.inactive_hours + hours
|
||||
return await self.residents_dao.update(resident_id, inactive_hours=new_hours)
|
||||
return None
|
||||
|
||||
async def get_resident_by_id(self, resident_id: int) -> Resident | None:
|
||||
return await self.residents_dao.get_by_id(resident_id)
|
||||
|
||||
async def get_resident_by_user_id(self, user_id: int) -> Resident | None:
|
||||
return await self.residents_dao.get_by_user_id(user_id)
|
||||
|
||||
async def get_residents_by_room(self, room_id: int) -> list[Resident]:
|
||||
return await self.residents_dao.get_by_room(room_id)
|
||||
|
||||
async def get_available_residents(self) -> list[Resident]:
|
||||
return await self.residents_dao.get_available()
|
||||
|
||||
async def get_all_residents(self) -> list[Resident]:
|
||||
return await self.residents_dao.get_all()
|
||||
|
||||
async def delete_resident(self, resident_id: int) -> None:
|
||||
await self.residents_dao.delete(resident_id)
|
||||
@@ -0,0 +1,26 @@
|
||||
from dutylog.infrastructure.database.dao.rooms_dao import RoomsDAO
|
||||
from dutylog.infrastructure.database.models.room import Room
|
||||
|
||||
|
||||
class RoomsRepository:
|
||||
def __init__(self, rooms_dao: RoomsDAO):
|
||||
self.rooms_dao = rooms_dao
|
||||
|
||||
async def get_or_create_room(self, number: int) -> Room:
|
||||
room = await self.rooms_dao.get_by_number(number)
|
||||
if not room:
|
||||
room = Room(number=number)
|
||||
room = await self.rooms_dao.create(room)
|
||||
return room
|
||||
|
||||
async def get_room_by_id(self, room_id: int) -> Room | None:
|
||||
return await self.rooms_dao.get_by_id(room_id)
|
||||
|
||||
async def get_room_by_number(self, number: int) -> Room | None:
|
||||
return await self.rooms_dao.get_by_number(number)
|
||||
|
||||
async def get_all_rooms(self) -> list[Room]:
|
||||
return await self.rooms_dao.get_all()
|
||||
|
||||
async def delete_room(self, room_id: int) -> None:
|
||||
await self.rooms_dao.delete(room_id)
|
||||
@@ -41,20 +41,6 @@ class UsersRepository:
|
||||
async def set_admin_status(self, user_id: int, is_admin: bool) -> User | None:
|
||||
return await self.users_dao.update(user_id, is_admin=is_admin)
|
||||
|
||||
async def add_active_hours(self, user_id: int, hours: int) -> User | None:
|
||||
user = await self.users_dao.get_by_id(user_id)
|
||||
if user:
|
||||
new_hours = user.active_hours + hours
|
||||
return await self.users_dao.update(user_id, active_hours=new_hours)
|
||||
return None
|
||||
|
||||
async def add_inactive_hours(self, user_id: int, hours: int) -> User | None:
|
||||
user = await self.users_dao.get_by_id(user_id)
|
||||
if user:
|
||||
new_hours = user.inactive_hours + hours
|
||||
return await self.users_dao.update(user_id, inactive_hours=new_hours)
|
||||
return None
|
||||
|
||||
async def get_all_admins(self) -> list[User]:
|
||||
all_users = await self.users_dao.get_all()
|
||||
return [user for user in all_users if user.is_admin]
|
||||
|
||||
@@ -6,8 +6,12 @@ from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, async_sessionmaker
|
||||
from dutylog.infrastructure.database.config import create_engine, create_session_maker
|
||||
from dutylog.infrastructure.database.dao.users_dao import UsersDAO
|
||||
from dutylog.infrastructure.database.dao.hours_transactions_dao import HoursTransactionsDAO
|
||||
from dutylog.infrastructure.database.dao.rooms_dao import RoomsDAO
|
||||
from dutylog.infrastructure.database.dao.residents_dao import ResidentsDAO
|
||||
from dutylog.infrastructure.database.repositories.users_repository import UsersRepository
|
||||
from dutylog.infrastructure.database.repositories.hours_transactions_repository import HoursTransactionsRepository
|
||||
from dutylog.infrastructure.database.repositories.rooms_repository import RoomsRepository
|
||||
from dutylog.infrastructure.database.repositories.residents_repository import ResidentsRepository
|
||||
from dutylog.infrastructure.utils.config import Config, load_config
|
||||
|
||||
|
||||
@@ -43,6 +47,14 @@ class DAOProvider(Provider):
|
||||
def get_hours_transactions_dao(self, session: AsyncSession) -> HoursTransactionsDAO:
|
||||
return HoursTransactionsDAO(session)
|
||||
|
||||
@provide(scope=Scope.REQUEST)
|
||||
def get_rooms_dao(self, session: AsyncSession) -> RoomsDAO:
|
||||
return RoomsDAO(session)
|
||||
|
||||
@provide(scope=Scope.REQUEST)
|
||||
def get_residents_dao(self, session: AsyncSession) -> ResidentsDAO:
|
||||
return ResidentsDAO(session)
|
||||
|
||||
|
||||
class RepositoryProvider(Provider):
|
||||
@provide(scope=Scope.REQUEST)
|
||||
@@ -53,9 +65,18 @@ class RepositoryProvider(Provider):
|
||||
def get_hours_transactions_repository(
|
||||
self,
|
||||
transactions_dao: HoursTransactionsDAO,
|
||||
users_dao: UsersDAO,
|
||||
residents_dao: ResidentsDAO,
|
||||
) -> HoursTransactionsRepository:
|
||||
return HoursTransactionsRepository(transactions_dao, users_dao)
|
||||
return HoursTransactionsRepository(transactions_dao, residents_dao)
|
||||
|
||||
@provide(scope=Scope.REQUEST)
|
||||
def get_rooms_repository(self, rooms_dao: RoomsDAO) -> RoomsRepository:
|
||||
return RoomsRepository(rooms_dao)
|
||||
|
||||
@provide(scope=Scope.REQUEST)
|
||||
def get_residents_repository(self, residents_dao: ResidentsDAO) -> ResidentsRepository:
|
||||
return ResidentsRepository(residents_dao)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user