fix: removed crap, category on service and deal
This commit is contained in:
		
							
								
								
									
										33
									
								
								auth/jwt.py
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								auth/jwt.py
									
									
									
									
									
								
							@@ -1,33 +0,0 @@
 | 
				
			|||||||
from typing import Annotated
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from fastapi import HTTPException, Depends
 | 
					 | 
				
			||||||
from fastapi.security import OAuth2PasswordBearer
 | 
					 | 
				
			||||||
from sqlalchemy import select
 | 
					 | 
				
			||||||
from starlette import status
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from backend import config
 | 
					 | 
				
			||||||
from database import User
 | 
					 | 
				
			||||||
from jose import jwt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from database.base import DatabaseDependency
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
oauth2_scheme = OAuth2PasswordBearer("")
 | 
					 | 
				
			||||||
ALGORITHM = "HS256"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def generate_jwt_token(user: User):
 | 
					 | 
				
			||||||
    return jwt.encode({'sub': user.id}, settings.SECRET_KEY, algorithm=ALGORITHM)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def require_jwt_sub(token: Annotated[str, Depends(oauth2_scheme)]):
 | 
					 | 
				
			||||||
    payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[ALGORITHM])
 | 
					 | 
				
			||||||
    user_id = payload.get("sub")
 | 
					 | 
				
			||||||
    if not user_id:
 | 
					 | 
				
			||||||
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail='Invalid authorization credentials')
 | 
					 | 
				
			||||||
    return payload
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async def get_current_user(db_session: DatabaseDependency, user_id: Annotated[int, Depends(require_jwt_sub)]) -> User:
 | 
					 | 
				
			||||||
    user = await db_session.scalar(select(User).where(User.id == user_id))
 | 
					 | 
				
			||||||
    if user:
 | 
					 | 
				
			||||||
        return user
 | 
					 | 
				
			||||||
@@ -1,27 +0,0 @@
 | 
				
			|||||||
import hmac
 | 
					 | 
				
			||||||
import hashlib
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from backend import config
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _generate_hash(telegram_data: dict):
 | 
					 | 
				
			||||||
    data = telegram_data.copy()
 | 
					 | 
				
			||||||
    del data['hash']
 | 
					 | 
				
			||||||
    keys = sorted(data.keys())
 | 
					 | 
				
			||||||
    string_arr = []
 | 
					 | 
				
			||||||
    for key in keys:
 | 
					 | 
				
			||||||
        if data[key] is not None:
 | 
					 | 
				
			||||||
            string_arr.append(key + '=' + str(data[key]))
 | 
					 | 
				
			||||||
    string_cat = '\n'.join(string_arr)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    secret_key = hashlib.sha256(settings.TELEGRAM_BOT_TOKEN.encode('utf-8')).digest()
 | 
					 | 
				
			||||||
    hash_bytes = bytes(string_cat, 'utf-8')
 | 
					 | 
				
			||||||
    hmac_hash = hmac.new(secret_key, hash_bytes, hashlib.sha256).hexdigest()
 | 
					 | 
				
			||||||
    return hmac_hash
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def telegram_authorize(telegram_data: dict):
 | 
					 | 
				
			||||||
    generated_hash = _generate_hash(telegram_data)
 | 
					 | 
				
			||||||
    user_hash = telegram_data['hash']
 | 
					 | 
				
			||||||
    return generated_hash == user_hash
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@@ -9,7 +9,7 @@ from .marketplace import BaseMarketplace
 | 
				
			|||||||
from .shipping_warehouse import ShippingWarehouse
 | 
					from .shipping_warehouse import ShippingWarehouse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if TYPE_CHECKING:
 | 
					if TYPE_CHECKING:
 | 
				
			||||||
    from . import DealBillRequest
 | 
					    from . import DealBillRequest, ServicePriceCategory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@unique
 | 
					@unique
 | 
				
			||||||
@@ -23,6 +23,12 @@ class DealStatus(IntEnum):
 | 
				
			|||||||
    CANCELLED = 6
 | 
					    CANCELLED = 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DealPriceCategory(BaseModel):
 | 
				
			||||||
 | 
					    __tablename__ = 'deal_price_category'
 | 
				
			||||||
 | 
					    deal_id: Mapped[int] = mapped_column(ForeignKey('deals.id'), primary_key=True, unique=True)
 | 
				
			||||||
 | 
					    category_id: Mapped[int] = mapped_column(ForeignKey('service_price_category.id'), primary_key=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Deal(BaseModel):
 | 
					class Deal(BaseModel):
 | 
				
			||||||
    __tablename__ = 'deals'
 | 
					    __tablename__ = 'deals'
 | 
				
			||||||
    id = Column(Integer, autoincrement=True, primary_key=True, index=True)
 | 
					    id = Column(Integer, autoincrement=True, primary_key=True, index=True)
 | 
				
			||||||
@@ -64,6 +70,9 @@ class Deal(BaseModel):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    comment = Column(String, nullable=False, server_default='', comment='Коментарий к заданию')
 | 
					    comment = Column(String, nullable=False, server_default='', comment='Коментарий к заданию')
 | 
				
			||||||
    bill_request: Mapped[Optional['DealBillRequest']] = relationship(back_populates='deal', lazy='joined')
 | 
					    bill_request: Mapped[Optional['DealBillRequest']] = relationship(back_populates='deal', lazy='joined')
 | 
				
			||||||
 | 
					    category: Mapped[Optional["ServicePriceCategory"]] = relationship('ServicePriceCategory',
 | 
				
			||||||
 | 
					                                                                      secondary=DealPriceCategory.__table__,
 | 
				
			||||||
 | 
					                                                                      lazy='joined')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealStatusHistory(BaseModel):
 | 
					class DealStatusHistory(BaseModel):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,6 +42,10 @@ class Service(BaseModel):
 | 
				
			|||||||
                                lazy='selectin',
 | 
					                                lazy='selectin',
 | 
				
			||||||
                                order_by="asc(ServicePriceRange.from_quantity)",
 | 
					                                order_by="asc(ServicePriceRange.from_quantity)",
 | 
				
			||||||
                                cascade="all, delete-orphan")
 | 
					                                cascade="all, delete-orphan")
 | 
				
			||||||
 | 
					    category_prices = relationship('ServiceCategoryPrice',
 | 
				
			||||||
 | 
					                                   back_populates='service',
 | 
				
			||||||
 | 
					                                   lazy='selectin',
 | 
				
			||||||
 | 
					                                   cascade="all, delete-orphan")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ServicePriceRange(BaseModel):
 | 
					class ServicePriceRange(BaseModel):
 | 
				
			||||||
@@ -54,6 +58,23 @@ class ServicePriceRange(BaseModel):
 | 
				
			|||||||
    price = Column(Double, nullable=False, comment='Цена')
 | 
					    price = Column(Double, nullable=False, comment='Цена')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ServiceCategoryPrice(BaseModel):
 | 
				
			||||||
 | 
					    __tablename__ = 'service_category_prices'
 | 
				
			||||||
 | 
					    service_id: Mapped[int] = mapped_column(ForeignKey('services.id'), primary_key=True)
 | 
				
			||||||
 | 
					    category_id: Mapped[int] = mapped_column(ForeignKey('service_price_category.id'), primary_key=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    price: Mapped[float] = mapped_column(Double, nullable=False, comment='Цена')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    service: Mapped["Service"] = relationship('Service', lazy='joined', back_populates='category_prices')
 | 
				
			||||||
 | 
					    category: Mapped["ServicePriceCategory"] = relationship('ServicePriceCategory', lazy='joined')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ServicePriceCategory(BaseModel):
 | 
				
			||||||
 | 
					    __tablename__ = 'service_price_category'
 | 
				
			||||||
 | 
					    id: Mapped[int] = mapped_column(primary_key=True)
 | 
				
			||||||
 | 
					    name: Mapped[str] = mapped_column(nullable=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ServiceCategory(BaseModel):
 | 
					class ServiceCategory(BaseModel):
 | 
				
			||||||
    __tablename__ = 'service_categories'
 | 
					    __tablename__ = 'service_categories'
 | 
				
			||||||
    id = Column(Integer, autoincrement=True, primary_key=True, index=True)
 | 
					    id = Column(Integer, autoincrement=True, primary_key=True, index=True)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,7 @@ service_router = APIRouter(
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# region Services
 | 
				
			||||||
@service_router.get(
 | 
					@service_router.get(
 | 
				
			||||||
    '/get-all',
 | 
					    '/get-all',
 | 
				
			||||||
    response_model=ServiceGetAllResponse,
 | 
					    response_model=ServiceGetAllResponse,
 | 
				
			||||||
@@ -69,6 +70,10 @@ async def delete(
 | 
				
			|||||||
    return await ServiceService(session).delete(request)
 | 
					    return await ServiceService(session).delete(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# region Categories
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@service_router.get(
 | 
					@service_router.get(
 | 
				
			||||||
    '/categories/get-all',
 | 
					    '/categories/get-all',
 | 
				
			||||||
    response_model=ServiceGetAllCategoriesResponse,
 | 
					    response_model=ServiceGetAllCategoriesResponse,
 | 
				
			||||||
@@ -94,6 +99,9 @@ async def create_category(
 | 
				
			|||||||
    return await ServiceService(session).create_category(request)
 | 
					    return await ServiceService(session).create_category(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# region Types
 | 
				
			||||||
@service_router.get(
 | 
					@service_router.get(
 | 
				
			||||||
    '/types/get-all',
 | 
					    '/types/get-all',
 | 
				
			||||||
    response_model=BaseEnumListSchema,
 | 
					    response_model=BaseEnumListSchema,
 | 
				
			||||||
@@ -108,6 +116,10 @@ async def get_all_service_types(
 | 
				
			|||||||
    return BaseEnumListSchema(items=result)
 | 
					    return BaseEnumListSchema(items=result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# region Kits
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@service_router.get(
 | 
					@service_router.get(
 | 
				
			||||||
    '/kits/get-all',
 | 
					    '/kits/get-all',
 | 
				
			||||||
    response_model=GetAllServicesKitsResponse,
 | 
					    response_model=GetAllServicesKitsResponse,
 | 
				
			||||||
@@ -144,3 +156,60 @@ async def update_services_kit(
 | 
				
			|||||||
        request: UpdateServicesKitRequest
 | 
					        request: UpdateServicesKitRequest
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    return await ServiceService(session).update_kit(request)
 | 
					    return await ServiceService(session).update_kit(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# region Price Categories
 | 
				
			||||||
 | 
					# crud price categories
 | 
				
			||||||
 | 
					@service_router.get(
 | 
				
			||||||
 | 
					    '/price-categories/get-all',
 | 
				
			||||||
 | 
					    response_model=GetAllPriceCategoriesResponse,
 | 
				
			||||||
 | 
					    operation_id='get_all_price_categories',
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def get_all_price_categories(
 | 
				
			||||||
 | 
					        session: SessionDependency
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await ServiceService(session).get_all_price_categories()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@service_router.post(
 | 
				
			||||||
 | 
					    '/price-categories/create',
 | 
				
			||||||
 | 
					    response_model=CreatePriceCategoryResponse,
 | 
				
			||||||
 | 
					    operation_id='create_price_category',
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def create_price_category(
 | 
				
			||||||
 | 
					        session: SessionDependency,
 | 
				
			||||||
 | 
					        request: CreatePriceCategoryRequest
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await ServiceService(session).create_price_category(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@service_router.post(
 | 
				
			||||||
 | 
					    '/price-categories/update',
 | 
				
			||||||
 | 
					    response_model=UpdatePriceCategoryResponse,
 | 
				
			||||||
 | 
					    operation_id='update_price_category',
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def update_price_category(
 | 
				
			||||||
 | 
					        session: SessionDependency,
 | 
				
			||||||
 | 
					        request: UpdatePriceCategoryRequest
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await ServiceService(session).update_price_category(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@service_router.post(
 | 
				
			||||||
 | 
					    '/price-categories/delete',
 | 
				
			||||||
 | 
					    response_model=DeletePriceCategoryResponse,
 | 
				
			||||||
 | 
					    operation_id='delete_price_category',
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def delete_price_category(
 | 
				
			||||||
 | 
					        session: SessionDependency,
 | 
				
			||||||
 | 
					        request: DeletePriceCategoryRequest
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await ServiceService(session).delete_price_category(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# endregion
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,12 +3,13 @@ from typing import List, Optional, Union
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from pydantic import constr, field_validator
 | 
					from pydantic import constr, field_validator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from models import ServiceCategoryPrice, ServicePriceCategory
 | 
				
			||||||
from schemas.base import BaseSchema, OkMessageSchema
 | 
					from schemas.base import BaseSchema, OkMessageSchema
 | 
				
			||||||
from schemas.billing import DealBillRequestSchema
 | 
					from schemas.billing import DealBillRequestSchema
 | 
				
			||||||
from schemas.client import ClientSchema
 | 
					from schemas.client import ClientSchema
 | 
				
			||||||
from schemas.marketplace import BaseMarketplaceSchema
 | 
					from schemas.marketplace import BaseMarketplaceSchema
 | 
				
			||||||
from schemas.product import ProductSchema
 | 
					from schemas.product import ProductSchema
 | 
				
			||||||
from schemas.service import ServiceSchema
 | 
					from schemas.service import ServiceSchema, ServicePriceCategorySchema
 | 
				
			||||||
from schemas.shipping_warehouse import ShippingWarehouseSchema
 | 
					from schemas.shipping_warehouse import ShippingWarehouseSchema
 | 
				
			||||||
from schemas.user import UserSchema
 | 
					from schemas.user import UserSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -37,6 +38,7 @@ class DealSummary(BaseSchema):
 | 
				
			|||||||
    shipment_warehouse_id: Optional[int]
 | 
					    shipment_warehouse_id: Optional[int]
 | 
				
			||||||
    shipment_warehouse_name: Optional[str]
 | 
					    shipment_warehouse_name: Optional[str]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealServiceSchema(BaseSchema):
 | 
					class DealServiceSchema(BaseSchema):
 | 
				
			||||||
    service: ServiceSchema
 | 
					    service: ServiceSchema
 | 
				
			||||||
    quantity: int
 | 
					    quantity: int
 | 
				
			||||||
@@ -81,6 +83,7 @@ class DealSchema(BaseSchema):
 | 
				
			|||||||
    comment: str
 | 
					    comment: str
 | 
				
			||||||
    shipping_warehouse: Optional[Union[ShippingWarehouseSchema, str]] = None
 | 
					    shipping_warehouse: Optional[Union[ShippingWarehouseSchema, str]] = None
 | 
				
			||||||
    bill_request: Optional[DealBillRequestSchema] = None
 | 
					    bill_request: Optional[DealBillRequestSchema] = None
 | 
				
			||||||
 | 
					    category: Optional[ServicePriceCategorySchema] = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealGeneralInfoSchema(BaseSchema):
 | 
					class DealGeneralInfoSchema(BaseSchema):
 | 
				
			||||||
@@ -110,6 +113,7 @@ class DealQuickCreateRequest(BaseSchema):
 | 
				
			|||||||
    acceptance_date: datetime.datetime
 | 
					    acceptance_date: datetime.datetime
 | 
				
			||||||
    shipping_warehouse: constr(strip_whitespace=True)
 | 
					    shipping_warehouse: constr(strip_whitespace=True)
 | 
				
			||||||
    base_marketplace: BaseMarketplaceSchema
 | 
					    base_marketplace: BaseMarketplaceSchema
 | 
				
			||||||
 | 
					    category: Optional[ServicePriceCategorySchema] = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealSummaryRequest(BaseSchema):
 | 
					class DealSummaryRequest(BaseSchema):
 | 
				
			||||||
@@ -212,9 +216,11 @@ class DealAddKitRequest(BaseSchema):
 | 
				
			|||||||
class DealCreateGuestUrlRequest(BaseSchema):
 | 
					class DealCreateGuestUrlRequest(BaseSchema):
 | 
				
			||||||
    deal_id: int
 | 
					    deal_id: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealCompleteRequest(BaseSchema):
 | 
					class DealCompleteRequest(BaseSchema):
 | 
				
			||||||
    deal_id: int
 | 
					    deal_id: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# endregion Requests
 | 
					# endregion Requests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# region Responses
 | 
					# region Responses
 | 
				
			||||||
@@ -311,6 +317,7 @@ class DealAddKitResponse(OkMessageSchema):
 | 
				
			|||||||
class DealCreateGuestUrlResponse(OkMessageSchema):
 | 
					class DealCreateGuestUrlResponse(OkMessageSchema):
 | 
				
			||||||
    url: str
 | 
					    url: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealCompleteResponse(OkMessageSchema):
 | 
					class DealCompleteResponse(OkMessageSchema):
 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,8 @@ from schemas.base import BaseSchema, OkMessageSchema, BaseEnumSchema
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# region Entities
 | 
					# region Entities
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# region Services
 | 
				
			||||||
class ServicePriceRangeSchema(BaseSchema):
 | 
					class ServicePriceRangeSchema(BaseSchema):
 | 
				
			||||||
    id: int | None
 | 
					    id: int | None
 | 
				
			||||||
    from_quantity: int
 | 
					    from_quantity: int
 | 
				
			||||||
@@ -16,6 +18,16 @@ class ServiceCategorySchema(BaseSchema):
 | 
				
			|||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ServicePriceCategorySchema(BaseSchema):
 | 
				
			||||||
 | 
					    id: int
 | 
				
			||||||
 | 
					    name: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ServiceCategoryPriceSchema(BaseSchema):
 | 
				
			||||||
 | 
					    category: ServicePriceCategorySchema
 | 
				
			||||||
 | 
					    price: float
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ServiceSchema(BaseSchema):
 | 
					class ServiceSchema(BaseSchema):
 | 
				
			||||||
    id: int
 | 
					    id: int
 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
@@ -23,9 +35,13 @@ class ServiceSchema(BaseSchema):
 | 
				
			|||||||
    price: float
 | 
					    price: float
 | 
				
			||||||
    service_type: int
 | 
					    service_type: int
 | 
				
			||||||
    price_ranges: List[ServicePriceRangeSchema]
 | 
					    price_ranges: List[ServicePriceRangeSchema]
 | 
				
			||||||
 | 
					    category_prices: List[ServiceCategoryPriceSchema]
 | 
				
			||||||
    cost: Optional[int]
 | 
					    cost: Optional[int]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# region Kits
 | 
				
			||||||
class BaseServiceKitSchema(BaseSchema):
 | 
					class BaseServiceKitSchema(BaseSchema):
 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
    service_type: int
 | 
					    service_type: int
 | 
				
			||||||
@@ -47,6 +63,12 @@ class UpdateServiceKitSchema(BaseServiceKitSchema):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# endregion
 | 
					# endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# region Category prices
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# region Requests
 | 
					# region Requests
 | 
				
			||||||
class ServiceCreateRequest(BaseSchema):
 | 
					class ServiceCreateRequest(BaseSchema):
 | 
				
			||||||
@@ -73,6 +95,19 @@ class UpdateServicesKitRequest(BaseSchema):
 | 
				
			|||||||
    data: UpdateServiceKitSchema
 | 
					    data: UpdateServiceKitSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreatePriceCategoryRequest(BaseSchema):
 | 
				
			||||||
 | 
					    name: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UpdatePriceCategoryRequest(BaseSchema):
 | 
				
			||||||
 | 
					    id: int
 | 
				
			||||||
 | 
					    name: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DeletePriceCategoryRequest(BaseSchema):
 | 
				
			||||||
 | 
					    id: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# endregion
 | 
					# endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -111,4 +146,21 @@ class UpdateServicesKitResponse(OkMessageSchema):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class GetAllServicesKitsResponse(BaseSchema):
 | 
					class GetAllServicesKitsResponse(BaseSchema):
 | 
				
			||||||
    services_kits: List[GetServiceKitSchema]
 | 
					    services_kits: List[GetServiceKitSchema]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GetAllPriceCategoriesResponse(BaseSchema):
 | 
				
			||||||
 | 
					    price_categories: List[ServicePriceCategorySchema]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreatePriceCategoryResponse(OkMessageSchema):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UpdatePriceCategoryResponse(OkMessageSchema):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DeletePriceCategoryResponse(OkMessageSchema):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# endregion
 | 
					# endregion
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -130,6 +130,14 @@ class DealService(BaseService):
 | 
				
			|||||||
                                 user,
 | 
					                                 user,
 | 
				
			||||||
                                 deadline=request.acceptance_date,
 | 
					                                 deadline=request.acceptance_date,
 | 
				
			||||||
                                 comment=request.comment)
 | 
					                                 comment=request.comment)
 | 
				
			||||||
 | 
					        # add category if specified
 | 
				
			||||||
 | 
					        if request.category:
 | 
				
			||||||
 | 
					            deal_category = DealPriceCategory(
 | 
				
			||||||
 | 
					                deal_id=deal.id,
 | 
				
			||||||
 | 
					                category_id=request.category.id
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            self.session.add(deal_category)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await self.session.commit()
 | 
					        await self.session.commit()
 | 
				
			||||||
        return DealQuickCreateResponse(deal_id=deal.id)
 | 
					        return DealQuickCreateResponse(deal_id=deal.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1004,7 +1012,7 @@ class DealService(BaseService):
 | 
				
			|||||||
        for product in deal.products:
 | 
					        for product in deal.products:
 | 
				
			||||||
            total_one_product = sum((service.price for service in product.services))
 | 
					            total_one_product = sum((service.price for service in product.services))
 | 
				
			||||||
            total = total_one_product * product.quantity
 | 
					            total = total_one_product * product.quantity
 | 
				
			||||||
            totals.append({ "total_one_product": total_one_product, "total": total })
 | 
					            totals.append({"total_one_product": total_one_product, "total": total})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return totals
 | 
					        return totals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,8 @@ from typing import Union
 | 
				
			|||||||
from sqlalchemy import select, update, insert, delete
 | 
					from sqlalchemy import select, update, insert, delete
 | 
				
			||||||
from sqlalchemy.orm import joinedload
 | 
					from sqlalchemy.orm import joinedload
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from models import Service, ServiceCategory, ServicePriceRange, ServicesKit, services_kit_services
 | 
					from models import Service, ServiceCategory, ServicePriceRange, ServicesKit, services_kit_services, \
 | 
				
			||||||
 | 
					    ServiceCategoryPrice, ServicePriceCategory
 | 
				
			||||||
from services.base import BaseService
 | 
					from services.base import BaseService
 | 
				
			||||||
from schemas.service import *
 | 
					from schemas.service import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -27,6 +28,7 @@ class ServiceService(BaseService):
 | 
				
			|||||||
            del service_dict['id']
 | 
					            del service_dict['id']
 | 
				
			||||||
            del service_dict['category']
 | 
					            del service_dict['category']
 | 
				
			||||||
            del service_dict['price_ranges']
 | 
					            del service_dict['price_ranges']
 | 
				
			||||||
 | 
					            del service_dict['category_prices']
 | 
				
			||||||
            service = Service(**service_dict)
 | 
					            service = Service(**service_dict)
 | 
				
			||||||
            self.session.add(service)
 | 
					            self.session.add(service)
 | 
				
			||||||
            await self.session.flush()
 | 
					            await self.session.flush()
 | 
				
			||||||
@@ -37,7 +39,15 @@ class ServiceService(BaseService):
 | 
				
			|||||||
                del price_range_dict['id']
 | 
					                del price_range_dict['id']
 | 
				
			||||||
                price_range_obj = ServicePriceRange(**price_range_dict)
 | 
					                price_range_obj = ServicePriceRange(**price_range_dict)
 | 
				
			||||||
                self.session.add(price_range_obj)
 | 
					                self.session.add(price_range_obj)
 | 
				
			||||||
 | 
					            category_prices = request.service.category_prices
 | 
				
			||||||
 | 
					            for category_price in category_prices:
 | 
				
			||||||
 | 
					                category_price_dict = category_price.model_dump()
 | 
				
			||||||
 | 
					                category_price_dict['service_id'] = service.id
 | 
				
			||||||
 | 
					                category_price_dict['category_id'] = category_price.category.id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                del category_price_dict['category']
 | 
				
			||||||
 | 
					                category_price_obj = ServiceCategoryPrice(**category_price_dict)
 | 
				
			||||||
 | 
					                self.session.add(category_price_obj)
 | 
				
			||||||
            await self.session.commit()
 | 
					            await self.session.commit()
 | 
				
			||||||
            return ServiceCreateResponse(ok=True, message="Услуга успешно создана")
 | 
					            return ServiceCreateResponse(ok=True, message="Услуга успешно создана")
 | 
				
			||||||
        except Exception as e:
 | 
					        except Exception as e:
 | 
				
			||||||
@@ -54,6 +64,7 @@ class ServiceService(BaseService):
 | 
				
			|||||||
            service_dict['category_id'] = raw_service.category.id
 | 
					            service_dict['category_id'] = raw_service.category.id
 | 
				
			||||||
            del service_dict['category']
 | 
					            del service_dict['category']
 | 
				
			||||||
            del service_dict['price_ranges']
 | 
					            del service_dict['price_ranges']
 | 
				
			||||||
 | 
					            del service_dict['category_prices']
 | 
				
			||||||
            await self.session.execute(
 | 
					            await self.session.execute(
 | 
				
			||||||
                update(Service)
 | 
					                update(Service)
 | 
				
			||||||
                .where(Service.id == raw_service.id)
 | 
					                .where(Service.id == raw_service.id)
 | 
				
			||||||
@@ -81,6 +92,26 @@ class ServiceService(BaseService):
 | 
				
			|||||||
                    del price_range_dict['id']
 | 
					                    del price_range_dict['id']
 | 
				
			||||||
                    price_range_obj = ServicePriceRange(**price_range_dict)
 | 
					                    price_range_obj = ServicePriceRange(**price_range_dict)
 | 
				
			||||||
                    self.session.add(price_range_obj)
 | 
					                    self.session.add(price_range_obj)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # deleting previouse category prices
 | 
				
			||||||
 | 
					            stmt = (
 | 
				
			||||||
 | 
					                delete(
 | 
				
			||||||
 | 
					                    ServiceCategoryPrice
 | 
				
			||||||
 | 
					                ).where(
 | 
				
			||||||
 | 
					                    ServiceCategoryPrice.service_id == service.id
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            await self.session.execute(stmt)
 | 
				
			||||||
 | 
					            await self.session.flush()
 | 
				
			||||||
 | 
					            # inserting new category prices
 | 
				
			||||||
 | 
					            for category_price in raw_service.category_prices:
 | 
				
			||||||
 | 
					                category_price_dict = category_price.dict()
 | 
				
			||||||
 | 
					                category_price_dict['service_id'] = raw_service.id
 | 
				
			||||||
 | 
					                category_price_dict['category_id'] = category_price.category.id
 | 
				
			||||||
 | 
					                del category_price_dict['category']
 | 
				
			||||||
 | 
					                category_price_obj = ServiceCategoryPrice(**category_price_dict)
 | 
				
			||||||
 | 
					                self.session.add(category_price_obj)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await self.session.commit()
 | 
					            await self.session.commit()
 | 
				
			||||||
            return ServiceUpdateResponse(ok=True, message="Услуга успешно обновлена")
 | 
					            return ServiceUpdateResponse(ok=True, message="Услуга успешно обновлена")
 | 
				
			||||||
        except Exception as e:
 | 
					        except Exception as e:
 | 
				
			||||||
@@ -205,3 +236,60 @@ class ServiceService(BaseService):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        except Exception as e:
 | 
					        except Exception as e:
 | 
				
			||||||
            return UpdateServicesKitResponse(ok=False, message=str(e))
 | 
					            return UpdateServicesKitResponse(ok=False, message=str(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def get_all_price_categories(self) -> GetAllPriceCategoriesResponse:
 | 
				
			||||||
 | 
					        query = await (self.session
 | 
				
			||||||
 | 
					                       .scalars(select(ServicePriceCategory)
 | 
				
			||||||
 | 
					                                .order_by(ServicePriceCategory.id)))
 | 
				
			||||||
 | 
					        price_categories = []
 | 
				
			||||||
 | 
					        for category in query.all():
 | 
				
			||||||
 | 
					            price_categories.append(ServicePriceCategorySchema.model_validate(category))
 | 
				
			||||||
 | 
					        return GetAllPriceCategoriesResponse(price_categories=price_categories)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def create_price_category(self, request: CreatePriceCategoryRequest) -> ServiceCreateCategoryResponse:
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            raw_category = request.name
 | 
				
			||||||
 | 
					            category = ServicePriceCategory(name=raw_category)
 | 
				
			||||||
 | 
					            self.session.add(category)
 | 
				
			||||||
 | 
					            await self.session.commit()
 | 
				
			||||||
 | 
					            return ServiceCreateCategoryResponse(ok=True, message="Категория цен успешно создана")
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            return ServiceCreateCategoryResponse(ok=False, message=f"Неудалось создать категорию цен, ошибка: {e}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def update_price_category(self, request: UpdatePriceCategoryRequest) -> ServiceUpdateResponse:
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            raw_category = request.name
 | 
				
			||||||
 | 
					            category = await (self.session.get(ServicePriceCategory, request.id))
 | 
				
			||||||
 | 
					            if not category:
 | 
				
			||||||
 | 
					                return ServiceUpdateResponse(ok=False, message="Категория цен не найдена")
 | 
				
			||||||
 | 
					            await self.session.execute(
 | 
				
			||||||
 | 
					                update(ServicePriceCategory)
 | 
				
			||||||
 | 
					                .where(ServicePriceCategory.id == request.id)
 | 
				
			||||||
 | 
					                .values(name=raw_category)
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            await self.session.commit()
 | 
				
			||||||
 | 
					            return ServiceUpdateResponse(ok=True, message="Категория цен успешно обновлена")
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            return ServiceUpdateResponse(ok=False, message=f"Неудалось обновить категорию цен, ошибка: {e}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def delete_price_category(self, request: DeletePriceCategoryRequest) -> ServiceDeleteResponse:
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            category = await (
 | 
				
			||||||
 | 
					                self.session
 | 
				
			||||||
 | 
					                .scalar(
 | 
				
			||||||
 | 
					                    select(
 | 
				
			||||||
 | 
					                        ServicePriceCategory
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .filter(
 | 
				
			||||||
 | 
					                        ServicePriceCategory.id == request.id
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            if not category:
 | 
				
			||||||
 | 
					                return ServiceDeleteResponse(ok=False, message="Категория цен не найдена")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            await self.session.delete(category)
 | 
				
			||||||
 | 
					            await self.session.commit()
 | 
				
			||||||
 | 
					            return ServiceDeleteResponse(ok=True, message="Категория цен успешно удалена")
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            return ServiceDeleteResponse(ok=False, message=f"Неудалось удалить категорию цен, ошибка: {e}")
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user