feat: time tracking in minutes
This commit is contained in:
@@ -47,5 +47,5 @@ class PaymentRecord(BaseModel):
|
||||
payroll_scheme_key: Mapped[int] = mapped_column(ForeignKey("payroll_schemas.key"), nullable=False)
|
||||
payroll_scheme: Mapped["PayrollScheme"] = relationship()
|
||||
|
||||
work_units: Mapped[int] = mapped_column(nullable=False)
|
||||
work_units: Mapped[float] = mapped_column(nullable=False)
|
||||
amount: Mapped[float] = mapped_column(Double, nullable=False)
|
||||
|
||||
@@ -11,7 +11,7 @@ class PaymentRecordSchemaBase(BaseSchema):
|
||||
start_date: datetime.date
|
||||
end_date: datetime.date
|
||||
|
||||
work_units: int
|
||||
work_units: float
|
||||
user: UserSchema
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ class PaymentRecordGetSchema(PaymentRecordSchemaBase):
|
||||
id: int
|
||||
created_by_user: UserSchema
|
||||
payroll_scheme: PayrollSchemeSchema
|
||||
amount: int
|
||||
amount: float
|
||||
created_at: datetime.datetime
|
||||
|
||||
|
||||
|
||||
@@ -8,13 +8,13 @@ from schemas.user import UserSchema
|
||||
# region Entities
|
||||
class TimeTrackingData(BaseSchema):
|
||||
date: datetime.date
|
||||
hours: int
|
||||
amount: int
|
||||
hours: float
|
||||
amount: float
|
||||
|
||||
|
||||
class TimeTrackingRecord(BaseSchema):
|
||||
user: UserSchema
|
||||
total_amount: int
|
||||
total_amount: float
|
||||
data: List[TimeTrackingData]
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class GetTimeTrackingRecordsRequest(BaseSchema):
|
||||
class UpdateTimeTrackingRecordRequest(BaseSchema):
|
||||
user_id: int
|
||||
date: datetime.date
|
||||
hours: int
|
||||
hours: float
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
@@ -170,7 +170,7 @@ class PayrollService(BaseService):
|
||||
def get_amount(
|
||||
self,
|
||||
user: User,
|
||||
work_units: int
|
||||
work_units: float
|
||||
):
|
||||
pay_rate: PayRate = user.pay_rate
|
||||
overtime_threshold = 0
|
||||
@@ -185,7 +185,7 @@ class PayrollService(BaseService):
|
||||
base_units = work_units
|
||||
overtime_units = 0
|
||||
else:
|
||||
overtime_units = max(0, work_units - overtime_threshold)
|
||||
overtime_units = max(0.0, work_units - overtime_threshold)
|
||||
base_units = work_units - overtime_units
|
||||
|
||||
return pay_rate.base_rate * base_units + overtime_rate * overtime_units
|
||||
|
||||
@@ -10,6 +10,7 @@ from schemas.work_shifts import StartShiftResponse, FinishShiftResponse, ActiveW
|
||||
FinishShiftByIdResponse
|
||||
from services.base import BaseService
|
||||
from services.time_tracking import TimeTrackingService
|
||||
from utils.work_time import hours_to_hours_and_minutes
|
||||
|
||||
|
||||
class WorkShiftsService(BaseService):
|
||||
@@ -59,7 +60,7 @@ class WorkShiftsService(BaseService):
|
||||
await self.session.commit()
|
||||
|
||||
diff: timedelta = work_shift.finished_at - work_shift.started_at
|
||||
hours = int(diff.total_seconds() // 3600)
|
||||
hours = diff.total_seconds() / 3600
|
||||
|
||||
data = UpdateTimeTrackingRecordRequest(
|
||||
user_id=user_id,
|
||||
@@ -68,7 +69,8 @@ class WorkShiftsService(BaseService):
|
||||
)
|
||||
await TimeTrackingService(self.session).update_record(user, data)
|
||||
|
||||
return FinishShiftResponse(ok=True, message=f"Смена закончена. Отработано {hours} ч.")
|
||||
hours, minutes = hours_to_hours_and_minutes(hours)
|
||||
return FinishShiftResponse(ok=True, message=f"Смена закончена. Отработано {hours} ч. {minutes} мин.")
|
||||
|
||||
async def finish_shift_by_id(self, user: User, shift_id: int) -> FinishShiftByIdResponse:
|
||||
work_shift = await self.session.get(WorkShift, shift_id)
|
||||
@@ -80,7 +82,7 @@ class WorkShiftsService(BaseService):
|
||||
await self.session.commit()
|
||||
|
||||
diff: timedelta = work_shift.finished_at - work_shift.started_at
|
||||
hours = int(diff.total_seconds() // 3600)
|
||||
hours = diff.total_seconds() / 3600
|
||||
|
||||
data = UpdateTimeTrackingRecordRequest(
|
||||
user_id=work_shift.user_id,
|
||||
@@ -89,7 +91,8 @@ class WorkShiftsService(BaseService):
|
||||
)
|
||||
await TimeTrackingService(self.session).update_record(user, data)
|
||||
|
||||
return FinishShiftByIdResponse(ok=True, message=f"Смена закончена. Отработано {hours} ч.")
|
||||
hours, minutes = hours_to_hours_and_minutes(hours)
|
||||
return FinishShiftByIdResponse(ok=True, message=f"Смена закончена. Отработано {hours} ч. {minutes} мин.")
|
||||
|
||||
async def get_active_shifts(self) -> ActiveWorkShiftsResponse:
|
||||
stmt = (
|
||||
|
||||
7
utils/work_time.py
Normal file
7
utils/work_time.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from math import floor
|
||||
|
||||
|
||||
def hours_to_hours_and_minutes(hours: float) -> tuple[int, int]:
|
||||
res_hours = int(floor(hours))
|
||||
minutes = int(round((hours - res_hours) * 60))
|
||||
return res_hours, minutes
|
||||
Reference in New Issue
Block a user