diff --git a/backend/dependecies.py b/backend/dependecies.py index e5acce2..f85b408 100644 --- a/backend/dependecies.py +++ b/backend/dependecies.py @@ -4,5 +4,11 @@ from fastapi import Depends from sqlalchemy.ext.asyncio import AsyncSession from backend.session import get_session +from models import User +from schemas.base import PaginationSchema +from services.auth import get_current_user +from utils.dependecies import pagination_parameters SessionDependency = Annotated[AsyncSession, Depends(get_session)] +PaginationDependency = Annotated[PaginationSchema, Depends(pagination_parameters)] +CurrentUserDependency = Annotated[User, Depends(get_current_user)] diff --git a/enums/payroll.py b/enums/payroll.py new file mode 100644 index 0000000..7000af9 --- /dev/null +++ b/enums/payroll.py @@ -0,0 +1,7 @@ +from enum import StrEnum + + +class PaySchemeType(StrEnum): + hourly = 'hourly' + daily = 'daily' + monthly = 'monthly' diff --git a/main.py b/main.py index c863c79..1171da9 100644 --- a/main.py +++ b/main.py @@ -40,6 +40,7 @@ routers_list = [ routers.user_router, routers.role_router, routers.marketplace_router, + routers.payroll_router, ] for router in routers_list: app.include_router(router) diff --git a/models/__init__.py b/models/__init__.py index e9e05d3..2b913c8 100644 --- a/models/__init__.py +++ b/models/__init__.py @@ -9,5 +9,6 @@ from .secondary import * from .barcode import * from .shipping_warehouse import * from .marketplace import * +from .payroll import * configure_mappers() diff --git a/models/auth.py b/models/auth.py index 84c1b60..1456c81 100644 --- a/models/auth.py +++ b/models/auth.py @@ -1,9 +1,14 @@ +from typing import TYPE_CHECKING + from sqlalchemy import BigInteger, Table, ForeignKey, Column from sqlalchemy.orm import Mapped, mapped_column, relationship from enums.user import UserRole from models.base import BaseModel +if TYPE_CHECKING: + from models.payroll import PayRate, PaymentRecord + role_permissions = Table( 'role_permissions', BaseModel.metadata, @@ -16,7 +21,12 @@ user_position = Table( BaseModel.metadata, Column('position_key', ForeignKey('positions.key'), primary_key=True), Column('user_id', ForeignKey('users.id'), primary_key=True, unique=True) - +) +user_pay_rate = Table( + 'user_pay_rate', + BaseModel.metadata, + Column('pay_rate_id', ForeignKey('pay_rates.id'), primary_key=True), + Column('user_id', ForeignKey('users.id'), primary_key=True, unique=True) ) @@ -69,6 +79,18 @@ class User(BaseModel): back_populates='users', lazy="joined" ) + pay_rate: Mapped["PayRate"] = relationship( + "PayRate", + secondary=user_pay_rate, + uselist=False, + lazy="joined" + ) + payment_records: Mapped[list["PaymentRecord"]] = relationship( + "PaymentRecord", + back_populates="user", + uselist=True, + foreign_keys="PaymentRecord.user_id" + ) class Position(BaseModel): diff --git a/models/payroll.py b/models/payroll.py new file mode 100644 index 0000000..e059896 --- /dev/null +++ b/models/payroll.py @@ -0,0 +1,51 @@ +import datetime +from typing import TYPE_CHECKING + +from sqlalchemy import ForeignKey, Double +from sqlalchemy.orm import mapped_column, Mapped, relationship + +from models.base import BaseModel + +if TYPE_CHECKING: + from models.auth import User + + +class PayrollScheme(BaseModel): + __tablename__ = 'payroll_schemas' + key: Mapped[str] = mapped_column(primary_key=True) + name: Mapped[str] = mapped_column(nullable=False) + + +class PayRate(BaseModel): + __tablename__ = 'pay_rates' + id: Mapped[int] = mapped_column(primary_key=True) + name: Mapped[str] = mapped_column(nullable=False) + + payroll_scheme_key: Mapped[int] = mapped_column(ForeignKey("payroll_schemas.key"), nullable=False) + payroll_scheme: Mapped["PayrollScheme"] = relationship(lazy="joined") + + base_rate: Mapped[float] = mapped_column(Double, nullable=False) + + overtime_rate: Mapped[float] = mapped_column(Double, nullable=True) + overtime_threshold: Mapped[int] = mapped_column(nullable=True) + + +class PaymentRecord(BaseModel): + __tablename__ = 'payment_records' + id: Mapped[int] = mapped_column(primary_key=True) + + user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), nullable=False) + user: Mapped["User"] = relationship(back_populates="payment_records", foreign_keys=[user_id]) + + 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]) + + start_date: Mapped[datetime.date] = mapped_column(nullable=False) + end_date: Mapped[datetime.date] = mapped_column(nullable=False) + created_at: Mapped[datetime.datetime] = mapped_column(nullable=False) + + 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) + amount: Mapped[float] = mapped_column(Double, nullable=False) diff --git a/routers/__init__.py b/routers/__init__.py index 2c8fa1d..b3009b4 100644 --- a/routers/__init__.py +++ b/routers/__init__.py @@ -9,3 +9,4 @@ from .position import position_router from .user import user_router from .role import role_router from .marketplace import marketplace_router +from .payroll import payroll_router diff --git a/routers/payroll.py b/routers/payroll.py new file mode 100644 index 0000000..3d86b99 --- /dev/null +++ b/routers/payroll.py @@ -0,0 +1,117 @@ +from fastapi import APIRouter + +from backend.dependecies import SessionDependency, PaginationDependency, CurrentUserDependency +from schemas.finances import CreatePayRateRequest, UpdatePayRateRequest, DeletePayRateRequest, \ + GetAllPayrollSchemeResponse, GetAllPayRatesResponse, CreatePayRateResponse, UpdatePayRateResponse, \ + DeletePayRateResponse +from schemas.payment_record import GetPaymentRecordsResponse, CreatePaymentRecordResponse, CreatePaymentRecordRequest, \ + DeletePaymentRecordResponse, DeletePaymentRecordRequest +from services.payroll import PayrollService + +payroll_router = APIRouter( + prefix="/payroll", + tags=["payroll"] +) + + +# region PayScheme +@payroll_router.get( + '/scheme/get-all', + operation_id='get_all_payroll_schemas', + response_model=GetAllPayrollSchemeResponse +) +async def get_all_schemas( + session: SessionDependency +): + return await PayrollService(session).get_all_schemas() + + +@payroll_router.get( + '/pay-rate/get-all', + operation_id='get_all_pay_rates', + response_model=GetAllPayRatesResponse +) +async def get_all_pay_rates( + session: SessionDependency +): + return await PayrollService(session).get_all_pay_rates() + + +# endregion + +# region PayRate +@payroll_router.post( + '/pay-rate/create', + operation_id='create_pay_rate', + response_model=CreatePayRateResponse +) +async def create_pay_rate( + session: SessionDependency, + request: CreatePayRateRequest +): + return await PayrollService(session).create_pay_rate(request) + + +@payroll_router.post( + '/pay-rate/update', + operation_id='update_pay_rate', + response_model=UpdatePayRateResponse +) +async def update_pay_rate( + session: SessionDependency, + request: UpdatePayRateRequest +): + return await PayrollService(session).update_pay_rate(request) + + +@payroll_router.post( + '/pay-rate/delete', + operation_id='delete_pay_rate', + response_model=DeletePayRateResponse +) +async def update_pay_rate( + session: SessionDependency, + request: DeletePayRateRequest +): + return await PayrollService(session).delete_pay_rate(request) + + +# endregion + +# region PaymentRecord +@payroll_router.get( + '/payment-record/get', + operation_id='get_payment_records', + response_model=GetPaymentRecordsResponse +) +async def get_payment_records( + session: SessionDependency, + pagination: PaginationDependency +): + return await PayrollService(session).get_payment_records(pagination) + + +@payroll_router.post( + '/payment-record/create', + operation_id='create_payment_record', + response_model=CreatePaymentRecordResponse +) +async def create_payment_records( + session: SessionDependency, + request: CreatePaymentRecordRequest, + user: CurrentUserDependency +): + return await PayrollService(session).create_payment_record(request, user) + + +@payroll_router.post( + '/payment-record/delete', + operation_id='delete_payment_record', + response_model=DeletePaymentRecordResponse +) +async def delete_payment_record( + session: SessionDependency, + request: DeletePaymentRecordRequest, +): + return await PayrollService(session).delete_payment_record(request) +# endregion diff --git a/schemas/finances.py b/schemas/finances.py new file mode 100644 index 0000000..762c3bb --- /dev/null +++ b/schemas/finances.py @@ -0,0 +1,44 @@ +from typing import List + +from schemas.base import BaseSchema, OkMessageSchema +from schemas.payrate import PayRateSchemaBase, PayRateSchema +from schemas.payroll import PayrollSchemeSchema + + +# region Requests + +class CreatePayRateRequest(BaseSchema): + data: PayRateSchemaBase + + +class UpdatePayRateRequest(BaseSchema): + data: PayRateSchema + + +class DeletePayRateRequest(BaseSchema): + pay_rate_id: int + + +# endregion + +# region Responses + +class GetAllPayrollSchemeResponse(BaseSchema): + payroll_schemas: List[PayrollSchemeSchema] + + +class GetAllPayRatesResponse(BaseSchema): + pay_rates: List[PayRateSchema] + + +class CreatePayRateResponse(OkMessageSchema): + pass + + +class UpdatePayRateResponse(OkMessageSchema): + pass + + +class DeletePayRateResponse(OkMessageSchema): + pass +# endregion diff --git a/schemas/payment_record.py b/schemas/payment_record.py new file mode 100644 index 0000000..4b8576d --- /dev/null +++ b/schemas/payment_record.py @@ -0,0 +1,55 @@ +import datetime +from typing import List + +from schemas.base import BaseSchema, PaginationInfoSchema, OkMessageSchema +from schemas.payroll import PayrollSchemeSchema +from schemas.user import UserSchema + + +# region Entities +class PaymentRecordSchemaBase(BaseSchema): + start_date: datetime.date + end_date: datetime.date + + work_units: int + user: UserSchema + + +class PaymentRecordCreateSchema(PaymentRecordSchemaBase): + pass + + +class PaymentRecordGetSchema(PaymentRecordSchemaBase): + id: int + created_by_user: UserSchema + payroll_scheme: PayrollSchemeSchema + amount: int + created_at: datetime.datetime + + +# endregion + +# region Requests +class CreatePaymentRecordRequest(BaseSchema): + data: PaymentRecordCreateSchema + + +class DeletePaymentRecordRequest(BaseSchema): + payment_record_id: int + + +# endregion + +# region Responses +class GetPaymentRecordsResponse(BaseSchema): + payment_records: List[PaymentRecordGetSchema] + pagination_info: PaginationInfoSchema + + +class CreatePaymentRecordResponse(OkMessageSchema): + pass + + +class DeletePaymentRecordResponse(OkMessageSchema): + pass +# endregion diff --git a/schemas/payrate.py b/schemas/payrate.py new file mode 100644 index 0000000..fe3538f --- /dev/null +++ b/schemas/payrate.py @@ -0,0 +1,16 @@ +from typing import Optional + +from schemas.base import BaseSchema +from schemas.payroll import PayrollSchemeSchema + + +class PayRateSchemaBase(BaseSchema): + name: str + payroll_scheme: PayrollSchemeSchema + base_rate: float + overtime_rate: Optional[float] = None + overtime_threshold: Optional[float] = None + + +class PayRateSchema(PayRateSchemaBase): + id: int diff --git a/schemas/payroll.py b/schemas/payroll.py new file mode 100644 index 0000000..f244d1e --- /dev/null +++ b/schemas/payroll.py @@ -0,0 +1,20 @@ +from schemas.base import BaseSchema + + +# region Entities +class PayrollSchemeSchema(BaseSchema): + key: str + name: str + + +# endregion + +# region Requests + + +# endregion + +# region Responses + + +# endregion diff --git a/schemas/user.py b/schemas/user.py index 0f3b75b..a48a170 100644 --- a/schemas/user.py +++ b/schemas/user.py @@ -1,6 +1,7 @@ from typing import List, Optional from schemas.base import BaseSchema, OkMessageSchema +from schemas.payrate import PayRateSchema from schemas.position import PositionSchema from schemas.role import RoleSchema @@ -20,6 +21,7 @@ class BaseUser(BaseSchema): is_blocked: bool is_deleted: bool role_key: str + pay_rate: Optional[PayRateSchema] = None class UserSchema(BaseUser): diff --git a/services/payroll.py b/services/payroll.py new file mode 100644 index 0000000..6d18596 --- /dev/null +++ b/services/payroll.py @@ -0,0 +1,293 @@ +import datetime +import math +from typing import Optional + +from fastapi import HTTPException +from sqlalchemy import select, insert, update, delete, func +from sqlalchemy.orm import joinedload +from starlette import status + +import enums.payroll +from models import PayrollScheme, PayRate, user_pay_rate, PaymentRecord, User +from schemas.base import PaginationSchema, PaginationInfoSchema +from schemas.finances import CreatePayRateRequest, UpdatePayRateRequest, DeletePayRateRequest, \ + GetAllPayrollSchemeResponse, GetAllPayRatesResponse, CreatePayRateResponse, UpdatePayRateResponse, \ + DeletePayRateResponse +from schemas.payment_record import GetPaymentRecordsResponse, PaymentRecordGetSchema, CreatePaymentRecordRequest, \ + CreatePaymentRecordResponse, PaymentRecordCreateSchema, DeletePaymentRecordRequest, DeletePaymentRecordResponse +from services.base import BaseService +from schemas.payroll import * +from utils.dependecies import is_valid_pagination + + +class PayrollService(BaseService): + async def get_all_schemas(self) -> GetAllPayrollSchemeResponse: + stmt = (select(PayrollScheme).order_by(PayrollScheme.key)) + payroll_schemas = (await self.session.scalars(stmt)).all() + return GetAllPayrollSchemeResponse( + payroll_schemas=PayrollSchemeSchema.from_orm_list(payroll_schemas) + ) + + async def get_all_pay_rates(self) -> GetAllPayRatesResponse: + stmt = ( + select( + PayRate + ).order_by( + PayRate.id + ) + .options( + joinedload(PayRate.payroll_scheme) + ) + ) + pay_rates = (await self.session.scalars(stmt)).all() + return GetAllPayRatesResponse( + pay_rates=pay_rates + ) + + async def create_pay_rate(self, request: CreatePayRateRequest) -> CreatePayRateResponse: + try: + # Preventing duplicate by name + if await self.session.scalar(select(PayRate).where(PayRate.name == request.data.name)): + return CreatePayRateResponse(ok=False, message="Тариф с таким названием уже существует") + pay_rate_dict = request.data.model_dump() + del pay_rate_dict['payroll_scheme'] + pay_rate_dict['payroll_scheme_key'] = request.data.payroll_scheme.key + + stmt = ( + insert(PayRate) + .values(**pay_rate_dict) + ) + await self.session.execute(stmt) + await self.session.commit() + + return CreatePayRateResponse(ok=True, message='Тариф успешно создан') + except Exception as e: + return CreatePayRateResponse(ok=False, message=str(e)) + + async def update_pay_rate(self, request: UpdatePayRateRequest) -> UpdatePayRateResponse: + try: + # Preventing duplicate by name + stmt = ( + select( + PayRate + ).where( + PayRate.id == request.data.id + ) + ) + pay_rate = await self.session.scalar(stmt) + if not pay_rate: + return CreatePayRateResponse(ok=False, message="Указанный тариф несуществует") + pay_rate_dict = request.data.model_dump() + del pay_rate_dict['payroll_scheme'] + pay_rate_dict['payroll_scheme_key'] = request.data.payroll_scheme.key + + stmt = ( + update(PayRate) + .values(**pay_rate_dict).where( + PayRate.id == request.data.id + ) + ) + await self.session.execute(stmt) + await self.session.commit() + + return CreatePayRateResponse(ok=True, message='Тариф успешно обновлен') + except Exception as e: + return CreatePayRateResponse(ok=False, message=str(e)) + + async def delete_pay_rate(self, request: DeletePayRateRequest) -> DeletePayRateResponse: + try: + user_pay_rate_record = await ( + self.session.scalar( + select( + user_pay_rate + ) + .where( + user_pay_rate.c.pay_rate_id == request.pay_rate_id + ) + ) + ) + if user_pay_rate_record: + return DeletePayRateResponse(ok=False, message="Указанный тариф привязан к пользователю") + stmt = ( + delete( + PayRate + ) + .where( + PayRate.id == request.pay_rate_id + ) + ) + await self.session.execute(stmt) + await self.session.commit() + return DeletePayRateResponse(ok=True, message="Тариф успешно удален") + except Exception as e: + return DeletePayRateResponse(ok=False, message=str(e)) + + async def get_payment_records(self, pagination: PaginationSchema) -> GetPaymentRecordsResponse: + if not is_valid_pagination(pagination): + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Invalid pagination') + page = max(0, pagination.page - 1) + stmt = ( + select( + PaymentRecord + ) + .options( + joinedload(PaymentRecord.payroll_scheme), + joinedload(PaymentRecord.user).noload(User.payment_records), + joinedload(PaymentRecord.created_by_user), + ) + .order_by( + PaymentRecord.created_at.desc() + ) + .offset( + page * pagination.items_per_page + ) + .limit( + pagination.items_per_page + ) + ) + total_records = await self.session.scalar(select(func.count()).select_from(PaymentRecord)) + if not total_records: + return GetPaymentRecordsResponse( + payment_records=[], + pagination_info=PaginationInfoSchema( + total_pages=0, + total_items=0 + ) + ) + total_items = total_records + total_pages = math.ceil(total_records / pagination.items_per_page) + + payment_records = (await self.session.scalars(stmt)).all() + response = GetPaymentRecordsResponse( + payment_records=PaymentRecordGetSchema.from_orm_list(payment_records), + pagination_info=PaginationInfoSchema( + total_items=total_items, + total_pages=total_pages + ) + ) + return response + + async def _create_payment_record_hourly( + self, + creator: User, + user: User, + record_schema: PaymentRecordCreateSchema + ): + pay_rate: PayRate = user.pay_rate + overtime_threshold = 0 + overtime_rate = 0 + + if pay_rate.overtime_threshold: + overtime_threshold = pay_rate.overtime_threshold + if pay_rate.overtime_rate: + overtime_rate = pay_rate.overtime_rate + + if overtime_threshold == 0 or overtime_rate == 0: + base_units = record_schema.work_units + overtime_units = 0 + else: + overtime_units = max(0, record_schema.work_units - overtime_threshold) + base_units = record_schema.work_units - overtime_units + + amount = pay_rate.base_rate * base_units + overtime_rate * overtime_units + payment_record_dict = record_schema.model_dump() + del payment_record_dict['user'] + payment_record_dict.update({ + 'created_by_user_id': creator.id, + 'created_at': datetime.datetime.now(), + 'payroll_scheme_key': pay_rate.payroll_scheme.key, + 'amount': amount, + 'user_id': record_schema.user.id + }) + stmt = ( + insert( + PaymentRecord + ).values( + **payment_record_dict + ) + ) + await self.session.execute(stmt) + await self.session.commit() + + async def _create_payment_record_daily( + self, + creator: User, + user: User, + record_schema: PaymentRecordCreateSchema + ): + pay_rate: PayRate = user.pay_rate + amount = pay_rate.base_rate * record_schema.work_units + payment_record_dict = record_schema.model_dump() + del payment_record_dict['user'] + + payment_record_dict.update({ + 'created_by_user_id': creator.id, + 'created_at': datetime.datetime.now(), + 'payroll_scheme_key': pay_rate.payroll_scheme.key, + 'amount': amount, + 'user_id': record_schema.user.id + + }) + + async def _create_payment_record_monthly( + self, + creator: User, + + user: User, + record_schema: PaymentRecordCreateSchema + ) -> CreatePaymentRecordResponse: + pay_rate: PayRate = user.pay_rate + amount = pay_rate.base_rate * record_schema.work_units + payment_record_dict = record_schema.model_dump() + del payment_record_dict['user'] + + payment_record_dict.update({ + 'created_by_user_id': creator.id, + 'created_at': datetime.datetime.now(), + 'payroll_scheme_key': pay_rate.payroll_scheme.key, + 'amount': amount, + 'user_id': record_schema.user.id + + }) + + async def create_payment_record( + self, + request: CreatePaymentRecordRequest, + creator: User + ) -> CreatePaymentRecordResponse: + try: + user: Optional[User] = await self.session.scalar(select(User).where(User.id == request.data.user.id)) + if not user: + return CreatePaymentRecordResponse(ok=False, message='Указанный пользователь не найден') + if not user.pay_rate: + return CreatePaymentRecordResponse(ok=False, message='У пользователя не указан тариф') + user_payroll_scheme = user.pay_rate.payroll_scheme.key + + if user_payroll_scheme == enums.payroll.PaySchemeType.hourly: + await self._create_payment_record_hourly(creator, user, request.data) + if user_payroll_scheme == enums.payroll.PaySchemeType.daily: + await self._create_payment_record_hourly(creator, user, request.data) + if user_payroll_scheme == enums.payroll.PaySchemeType.monthly: + await self._create_payment_record_hourly(creator, user, request.data) + + return CreatePaymentRecordResponse(ok=True, message='Запись успешно добавлена') + except Exception as e: + return CreatePaymentRecordResponse(ok=False, message=str(e)) + + async def delete_payment_record( + self, + request: DeletePaymentRecordRequest + ) -> DeletePaymentRecordResponse: + try: + stmt = ( + delete( + PaymentRecord + ).where( + PaymentRecord.id == request.payment_record_id + ) + ) + await self.session.execute(stmt) + await self.session.commit() + return DeletePayRateResponse(ok=True, message="Начисление успешно удалено") + except Exception as e: + return DeletePayRateResponse(ok=False, message=str(e)) diff --git a/services/user.py b/services/user.py index 1d84de9..22d4d07 100644 --- a/services/user.py +++ b/services/user.py @@ -1,6 +1,6 @@ from sqlalchemy import select, update, delete, insert -from models import User, user_position +from models import User, user_position, user_pay_rate from services.base import BaseService from schemas.user import * @@ -21,28 +21,38 @@ class UserService(BaseService): async def update(self, request: UpdateUserRequest) -> UpdateUserResponse: try: - if not self.get_by_id(request.data.id): + if not await self.get_by_id(request.data.id): return UpdateUserResponse(ok=False, message='Указанный пользователь не найден') base_fields = request.data.model_dump_parent() + del base_fields['pay_rate'] stmt = update(User).values(**base_fields).where(User.id == request.data.id) - print(stmt) await self.session.execute(stmt) await self.session.flush() - # Updating position + # Deleting previous position stmt = delete(user_position).where(user_position.c.user_id == request.data.id) await self.session.execute(stmt) await self.session.flush() - if not request.data.position_key: - await self.session.commit() - return UpdateUserResponse(ok=True, message='Пользователь успешно обновлен') - stmt = insert(user_position).values(**{ - 'user_id': request.data.id, - 'position_key': request.data.position_key - }) + # Deleting previous pay rate + stmt = delete(user_pay_rate).where(user_pay_rate.c.user_id == request.data.id) await self.session.execute(stmt) + await self.session.flush() + + if request.data.position_key: + stmt = insert(user_position).values(**{ + 'user_id': request.data.id, + 'position_key': request.data.position_key + }) + await self.session.execute(stmt) + if request.data.pay_rate: + stmt = insert(user_pay_rate).values(**{ + 'user_id': request.data.id, + 'pay_rate_id': request.data.pay_rate.id + }) + await self.session.execute(stmt) + await self.session.commit() return UpdateUserResponse(ok=True, message='Пользователь успешно обновлен') except Exception as e: - pass + return UpdateUserResponse(ok=False, message=str(e)) diff --git a/static/icons/ozon.png b/static/icons/ozon.png index 52293bf..1effefc 100644 Binary files a/static/icons/ozon.png and b/static/icons/ozon.png differ diff --git a/test.py b/test.py index b262575..0d6471d 100644 --- a/test.py +++ b/test.py @@ -1,3 +1,28 @@ -a = {1, 2, 3} -b = {4, 5, 6} -print(a.union(b)) +import asyncio + +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession + +from backend.session import session_maker +from models import User + + +async def main(): + work_units = 15 + base_rate = 0 + overtime_units = max([0, work_units - base_rate]) + base_units = work_units - overtime_units + print(overtime_units, base_units) + return + session: AsyncSession = session_maker() + a = await session.scalar( + select(User).where(User.first_name == "Абид") + + ) + print(a) + await session.close() + + +if __name__ == '__main__': + loop = asyncio.get_event_loop() + loop.run_until_complete(main()) diff --git a/utils/init_marketplaces.py b/utils/init_marketplaces.py index 0b6769c..51f2872 100644 --- a/utils/init_marketplaces.py +++ b/utils/init_marketplaces.py @@ -19,12 +19,12 @@ async def main(): { 'key': BaseMarketplace.OZON, 'name': 'OZON', - 'icon_url': '/api/static/icons/ozon.svg' + 'icon_url': '/api/static/icons/ozon.png' }, { 'key': BaseMarketplace.YANDEX_MARKET, 'name': 'Яндекс Маркет', - 'icon_url': '/api/static/icons/ym.svg' + 'icon_url': '/api/static/icons/ym.png' } ] await session.execute(insert(models.BaseMarketplace), marketplaces) diff --git a/utils/init_payroll_schemas.py b/utils/init_payroll_schemas.py new file mode 100644 index 0000000..a45d002 --- /dev/null +++ b/utils/init_payroll_schemas.py @@ -0,0 +1,36 @@ +import asyncio + +from sqlalchemy import insert +from sqlalchemy.ext.asyncio import AsyncSession + +import models +from backend.session import session_maker +from enums.base_marketplace import BaseMarketplace +from enums.payroll import PaySchemeType + + +async def main(): + session: AsyncSession = session_maker() + schemas = [ + { + 'key': PaySchemeType.hourly, + 'name': 'Почасовая', + }, + { + 'key': PaySchemeType.daily, + 'name': 'Подневная', + }, + { + 'key': PaySchemeType.monthly, + 'name': 'Помесячная', + + } + ] + await session.execute(insert(models.PayrollScheme), schemas) + await session.commit() + await session.close() + + +if __name__ == '__main__': + loop = asyncio.get_event_loop() + loop.run_until_complete(main())