feat: work shifts history
This commit is contained in:
@@ -29,7 +29,7 @@ class Expense(BaseModel):
|
||||
amount: Mapped[float] = mapped_column()
|
||||
|
||||
created_by_user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), nullable=False)
|
||||
created_by_user: Mapped["User"] = relationship(foreign_keys=[created_by_user_id])
|
||||
created_by_user: Mapped["User"] = relationship(foreign_keys=[created_by_user_id], lazy="selectin")
|
||||
|
||||
tags: Mapped[list["ExpenseTag"]] = relationship(
|
||||
secondary=expenses_expense_tags,
|
||||
|
||||
@@ -27,4 +27,5 @@ class WorkShift(BaseModel):
|
||||
user: Mapped["User"] = relationship(
|
||||
"User",
|
||||
back_populates="work_shifts",
|
||||
lazy="selectin",
|
||||
)
|
||||
|
||||
@@ -2,10 +2,9 @@ from io import BytesIO
|
||||
|
||||
from fastapi import APIRouter, Response
|
||||
|
||||
from backend.dependecies import SessionDependency, CurrentUserDependency
|
||||
from backend.dependecies import SessionDependency, CurrentUserDependency, PaginationDependency
|
||||
from generators.work_shifts_qr_code_generator import WorkShiftsQRCodeGenerator
|
||||
from schemas.work_shifts import StartShiftResponse, FinishShiftResponse, ActiveWorkShiftsResponse, DeleteShiftResponse, \
|
||||
FinishShiftByIdResponse
|
||||
from schemas.work_shifts import *
|
||||
from services.work_shifts import WorkShiftsService
|
||||
|
||||
work_shifts_router = APIRouter(
|
||||
@@ -65,14 +64,16 @@ async def finish_work_shift_by_id(
|
||||
|
||||
|
||||
@work_shifts_router.get(
|
||||
"/get-active-shifts",
|
||||
response_model=ActiveWorkShiftsResponse,
|
||||
operation_id="get_active_shifts",
|
||||
"/get-shifts/{is_active}",
|
||||
response_model=GetWorkShiftsResponse,
|
||||
operation_id="get_shifts",
|
||||
)
|
||||
async def get_active_shifts(
|
||||
async def get_shifts(
|
||||
session: SessionDependency,
|
||||
pagination: PaginationDependency,
|
||||
is_active: bool,
|
||||
):
|
||||
return await WorkShiftsService(session).get_active_shifts()
|
||||
return await WorkShiftsService(session).get_shifts(is_active, pagination)
|
||||
|
||||
|
||||
@work_shifts_router.delete(
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
from datetime import datetime
|
||||
from typing import List
|
||||
from typing import List, Optional
|
||||
|
||||
from schemas.base import OkMessageSchema, BaseSchema
|
||||
from schemas.base import OkMessageSchema, BaseSchema, PaginationInfoSchema
|
||||
from schemas.user import UserSchema
|
||||
|
||||
|
||||
# region Entities
|
||||
|
||||
class ActiveWorkShiftSchema(BaseSchema):
|
||||
class WorkShiftSchema(BaseSchema):
|
||||
id: int
|
||||
started_at: datetime
|
||||
finished_at: Optional[datetime] = None
|
||||
hours: Optional[float] = None
|
||||
user: UserSchema
|
||||
|
||||
|
||||
@@ -29,8 +31,9 @@ class FinishShiftByIdResponse(OkMessageSchema):
|
||||
pass
|
||||
|
||||
|
||||
class ActiveWorkShiftsResponse(BaseSchema):
|
||||
shifts: List[ActiveWorkShiftSchema]
|
||||
class GetWorkShiftsResponse(BaseSchema):
|
||||
shifts: List[WorkShiftSchema]
|
||||
pagination_info: PaginationInfoSchema
|
||||
|
||||
|
||||
class DeleteShiftResponse(OkMessageSchema):
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
from datetime import datetime, date, timedelta
|
||||
from datetime import date, timedelta
|
||||
|
||||
from sqlalchemy import select, delete
|
||||
import math
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy import select, delete, func
|
||||
from sqlalchemy.orm import joinedload
|
||||
|
||||
from models import WorkShift, User
|
||||
from schemas.base import PaginationSchema
|
||||
from schemas.time_tracking import UpdateTimeTrackingRecordRequest
|
||||
from schemas.user import *
|
||||
from schemas.work_shifts import StartShiftResponse, FinishShiftResponse, ActiveWorkShiftsResponse, DeleteShiftResponse, \
|
||||
FinishShiftByIdResponse
|
||||
from schemas.work_shifts import *
|
||||
from services.base import BaseService
|
||||
from services.time_tracking import TimeTrackingService
|
||||
from utils.dependecies import is_valid_pagination
|
||||
from utils.work_time import hours_to_hours_and_minutes
|
||||
|
||||
|
||||
@@ -100,18 +102,44 @@ class WorkShiftsService(BaseService):
|
||||
hours, minutes = hours_to_hours_and_minutes(hours)
|
||||
return FinishShiftByIdResponse(ok=True, message=f"Смена закончена. Отработано {hours} ч. {minutes} мин.")
|
||||
|
||||
async def get_active_shifts(self) -> ActiveWorkShiftsResponse:
|
||||
async def get_shifts(self, is_active: bool, pagination: PaginationSchema) -> GetWorkShiftsResponse:
|
||||
if not is_valid_pagination(pagination):
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Invalid pagination')
|
||||
page = max(0, pagination.page - 1)
|
||||
|
||||
total_shifts = await self.session.scalar(
|
||||
select(func.count())
|
||||
.select_from(WorkShift)
|
||||
.where(WorkShift.finished_at.is_(None) if is_active else WorkShift.finished_at.is_not(None))
|
||||
)
|
||||
if not total_shifts:
|
||||
return GetWorkShiftsResponse(
|
||||
shifts=[],
|
||||
pagination_info=PaginationInfoSchema(
|
||||
total_pages=0,
|
||||
total_items=0
|
||||
)
|
||||
)
|
||||
|
||||
total_pages = math.ceil(total_shifts / pagination.items_per_page)
|
||||
|
||||
stmt = (
|
||||
select(WorkShift)
|
||||
.options(joinedload(WorkShift.user))
|
||||
.where(WorkShift.finished_at == None)
|
||||
.where(WorkShift.finished_at.is_(None) if is_active else WorkShift.finished_at.is_not(None))
|
||||
.order_by(WorkShift.started_at.desc())
|
||||
.offset(page * pagination.items_per_page)
|
||||
.limit(pagination.items_per_page)
|
||||
)
|
||||
shifts = (await self.session.execute(stmt)).scalars().all()
|
||||
|
||||
shifts = await self.session.execute(stmt)
|
||||
shifts = shifts.scalars().all()
|
||||
response = ActiveWorkShiftsResponse(shifts=shifts)
|
||||
return response
|
||||
return GetWorkShiftsResponse(
|
||||
shifts=shifts,
|
||||
pagination_info=PaginationInfoSchema(
|
||||
total_pages=total_pages,
|
||||
total_items=total_shifts,
|
||||
)
|
||||
)
|
||||
|
||||
async def delete_shift(self, shift_id: int) -> DeleteShiftResponse:
|
||||
stmt = (
|
||||
|
||||
Reference in New Issue
Block a user