crappy
This commit is contained in:
		
							
								
								
									
										3
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								main.py
									
									
									
									
									
								
							@@ -20,7 +20,8 @@ routers_list = [
 | 
				
			|||||||
    routers.auth_router,
 | 
					    routers.auth_router,
 | 
				
			||||||
    routers.deal_router,
 | 
					    routers.deal_router,
 | 
				
			||||||
    routers.client_router,
 | 
					    routers.client_router,
 | 
				
			||||||
    routers.service_router
 | 
					    routers.service_router,
 | 
				
			||||||
 | 
					    routers.product_router,
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
for router in routers_list:
 | 
					for router in routers_list:
 | 
				
			||||||
    app.include_router(router)
 | 
					    app.include_router(router)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@ from .auth import *
 | 
				
			|||||||
from .deal import *
 | 
					from .deal import *
 | 
				
			||||||
from .client import *
 | 
					from .client import *
 | 
				
			||||||
from .service import *
 | 
					from .service import *
 | 
				
			||||||
 | 
					from .product import *
 | 
				
			||||||
from .secondary import *
 | 
					from .secondary import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
configure_mappers()
 | 
					configure_mappers()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,8 @@ class Client(BaseModel):
 | 
				
			|||||||
    name = Column(String, nullable=False, unique=True, comment='Название клиента')
 | 
					    name = Column(String, nullable=False, unique=True, comment='Название клиента')
 | 
				
			||||||
    created_at = Column(DateTime, nullable=False, comment='Дата создания')
 | 
					    created_at = Column(DateTime, nullable=False, comment='Дата создания')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    products = relationship('Product', back_populates='client')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ClientDetails(BaseModel):
 | 
					class ClientDetails(BaseModel):
 | 
				
			||||||
    __tablename__ = 'client_details'
 | 
					    __tablename__ = 'client_details'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,6 @@ from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Boolean
 | 
				
			|||||||
from sqlalchemy.orm import relationship
 | 
					from sqlalchemy.orm import relationship
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from models.base import BaseModel
 | 
					from models.base import BaseModel
 | 
				
			||||||
from models.secondary import deal_services
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@unique
 | 
					@unique
 | 
				
			||||||
@@ -33,7 +32,7 @@ class Deal(BaseModel):
 | 
				
			|||||||
    is_deleted = Column(Boolean, nullable=False, server_default='0', default=False, comment='Удалена')
 | 
					    is_deleted = Column(Boolean, nullable=False, server_default='0', default=False, comment='Удалена')
 | 
				
			||||||
    is_completed = Column(Boolean, nullable=False, server_default='0', default=False, comment='Завершена')
 | 
					    is_completed = Column(Boolean, nullable=False, server_default='0', default=False, comment='Завершена')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    services = relationship('Service', secondary=deal_services)
 | 
					    services = relationship('DealService', back_populates='deal')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealStatusHistory(BaseModel):
 | 
					class DealStatusHistory(BaseModel):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,5 +11,5 @@ class Product(BaseModel):
 | 
				
			|||||||
    article = Column(String, nullable=False, index=True)
 | 
					    article = Column(String, nullable=False, index=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    client_id = Column(Integer, ForeignKey('clients.id'), nullable=False, comment='ID сделки')
 | 
					    client_id = Column(Integer, ForeignKey('clients.id'), nullable=False, comment='ID сделки')
 | 
				
			||||||
    client = relationship('Client', back_populates='status_history')
 | 
					    client = relationship('Client', back_populates='products')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,15 @@
 | 
				
			|||||||
from sqlalchemy import Table, Column, Integer, ForeignKey
 | 
					from sqlalchemy import Table, Column, Integer, ForeignKey
 | 
				
			||||||
 | 
					from sqlalchemy.orm import relationship
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from models.base import metadata
 | 
					from models.base import metadata, BaseModel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
deal_services = Table(
 | 
					
 | 
				
			||||||
    'deal_services', metadata,
 | 
					class DealService(BaseModel):
 | 
				
			||||||
    Column('deal_id', Integer, ForeignKey('deals.id')),
 | 
					    __tablename__ = 'deal_services'
 | 
				
			||||||
    Column('service_id', Integer, ForeignKey('services.id')),
 | 
					    deal_id = Column(Integer, ForeignKey('deals.id'), nullable=False, comment='ID Сделки', primary_key=True)
 | 
				
			||||||
    Column('quantity', Integer)
 | 
					    deal = relationship('Deal', back_populates='services')
 | 
				
			||||||
)
 | 
					
 | 
				
			||||||
 | 
					    service_id = Column(Integer, ForeignKey('services.id'), nullable=False, comment='ID Услуги', primary_key=True)
 | 
				
			||||||
 | 
					    service = relationship('Service')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    quantity = Column(Integer, nullable=False, comment='Кол-во услуги')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,12 @@
 | 
				
			|||||||
from sqlalchemy import Column, Integer, String, ForeignKey, Double
 | 
					from sqlalchemy import Column, Integer, String, ForeignKey, Double
 | 
				
			||||||
from sqlalchemy.orm import relationship
 | 
					from sqlalchemy.orm import relationship, mapped_column, Mapped
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from models import BaseModel
 | 
					from models import BaseModel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Service(BaseModel):
 | 
					class Service(BaseModel):
 | 
				
			||||||
    __tablename__ = 'services'
 | 
					    __tablename__ = 'services'
 | 
				
			||||||
    id = Column(Integer, autoincrement=True, primary_key=True, index=True)
 | 
					    id: Mapped[int] = mapped_column(Integer, autoincrement=True, primary_key=True, index=True)
 | 
				
			||||||
    name = Column(String, nullable=False, comment='Название услуги')
 | 
					    name = Column(String, nullable=False, comment='Название услуги')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    category_id = Column(Integer, ForeignKey('service_categories.id'), nullable=False, comment='ID категории услуги')
 | 
					    category_id = Column(Integer, ForeignKey('service_categories.id'), nullable=False, comment='ID категории услуги')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,4 +2,4 @@ from .auth import auth_router
 | 
				
			|||||||
from .deal import deal_router
 | 
					from .deal import deal_router
 | 
				
			||||||
from .client import client_router
 | 
					from .client import client_router
 | 
				
			||||||
from .service import service_router
 | 
					from .service import service_router
 | 
				
			||||||
 | 
					from .product import product_router
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,3 +50,14 @@ async def get_summary(
 | 
				
			|||||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
					        session: Annotated[AsyncSession, Depends(get_session)]
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    return await DealService(session).get_summary()
 | 
					    return await DealService(session).get_summary()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@deal_router.post(
 | 
				
			||||||
 | 
					    '/services/add',
 | 
				
			||||||
 | 
					    response_model=DealAddServicesResponse,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def services_add(
 | 
				
			||||||
 | 
					        request: DealAddServicesRequest,
 | 
				
			||||||
 | 
					        session: Annotated[AsyncSession, Depends(get_session)]
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await DealService(session).add_services(request)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										39
									
								
								routers/product.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								routers/product.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					from typing import Annotated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from fastapi import APIRouter, Depends
 | 
				
			||||||
 | 
					from sqlalchemy.ext.asyncio import AsyncSession
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import utils.dependecies
 | 
				
			||||||
 | 
					from backend.session import get_session
 | 
				
			||||||
 | 
					from schemas.base import PaginationSchema
 | 
				
			||||||
 | 
					from schemas.product import *
 | 
				
			||||||
 | 
					from services.product import ProductService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					product_router = APIRouter(
 | 
				
			||||||
 | 
					    prefix="/product",
 | 
				
			||||||
 | 
					    tags=["product"]
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@product_router.post(
 | 
				
			||||||
 | 
					    '/create',
 | 
				
			||||||
 | 
					    response_model=ProductCreateResponse
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def create_product(
 | 
				
			||||||
 | 
					        request: ProductCreateRequest,
 | 
				
			||||||
 | 
					        session: Annotated[AsyncSession, Depends(get_session)]
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await ProductService(session).create(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@product_router.get(
 | 
				
			||||||
 | 
					    '/get',
 | 
				
			||||||
 | 
					    response_model=ProductGetResponse,
 | 
				
			||||||
 | 
					    operation_id='get_products_by_client_id'
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def get_product(
 | 
				
			||||||
 | 
					        client_id: int,
 | 
				
			||||||
 | 
					        pagination: Annotated[PaginationSchema, Depends(utils.dependecies.pagination_parameters)],
 | 
				
			||||||
 | 
					        session: Annotated[AsyncSession, Depends(get_session)]
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await ProductService(session).get_by_client_id(client_id, pagination)
 | 
				
			||||||
@@ -4,7 +4,7 @@ from fastapi import APIRouter, Depends
 | 
				
			|||||||
from sqlalchemy.ext.asyncio import AsyncSession
 | 
					from sqlalchemy.ext.asyncio import AsyncSession
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from backend.session import get_session
 | 
					from backend.session import get_session
 | 
				
			||||||
from schemas.services import *
 | 
					from schemas.service import *
 | 
				
			||||||
from services.service import ServiceService
 | 
					from services.service import ServiceService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
service_router = APIRouter(
 | 
					service_router = APIRouter(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,3 +14,13 @@ class CustomModel(BaseModel):
 | 
				
			|||||||
class OkMessageSchema(BaseModel):
 | 
					class OkMessageSchema(BaseModel):
 | 
				
			||||||
    ok: bool
 | 
					    ok: bool
 | 
				
			||||||
    message: str
 | 
					    message: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PaginationSchema(CustomModel):
 | 
				
			||||||
 | 
					    page: int
 | 
				
			||||||
 | 
					    items_per_page: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PaginationInfoSchema(CustomModel):
 | 
				
			||||||
 | 
					    total_pages: int
 | 
				
			||||||
 | 
					    total_items: int
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,12 @@ class DealSummary(CustomModel):
 | 
				
			|||||||
    client_name: str
 | 
					    client_name: str
 | 
				
			||||||
    changed_at: datetime.datetime
 | 
					    changed_at: datetime.datetime
 | 
				
			||||||
    status: int
 | 
					    status: int
 | 
				
			||||||
 | 
					    total_price: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DealServiceSchema(CustomModel):
 | 
				
			||||||
 | 
					    id: int
 | 
				
			||||||
 | 
					    quantity: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# endregion Entities
 | 
					# endregion Entities
 | 
				
			||||||
@@ -45,6 +51,11 @@ class DealSummaryRequest(CustomModel):
 | 
				
			|||||||
    pass
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DealAddServicesRequest(CustomModel):
 | 
				
			||||||
 | 
					    deal_id: int
 | 
				
			||||||
 | 
					    services: list[DealServiceSchema]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# endregion Requests
 | 
					# endregion Requests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# region Responses
 | 
					# region Responses
 | 
				
			||||||
@@ -64,4 +75,8 @@ class DealQuickCreateResponse(CustomModel):
 | 
				
			|||||||
class DealSummaryResponse(CustomModel):
 | 
					class DealSummaryResponse(CustomModel):
 | 
				
			||||||
    summaries: List[DealSummary]
 | 
					    summaries: List[DealSummary]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DealAddServicesResponse(CustomModel):
 | 
				
			||||||
 | 
					    ok: bool
 | 
				
			||||||
 | 
					    message: str
 | 
				
			||||||
# endregion Responses
 | 
					# endregion Responses
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										33
									
								
								schemas/product.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								schemas/product.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					from typing import List
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from schemas.base import CustomModel, PaginationInfoSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# region Entities
 | 
				
			||||||
 | 
					class ProductSchema(CustomModel):
 | 
				
			||||||
 | 
					    id: int
 | 
				
			||||||
 | 
					    name: str
 | 
				
			||||||
 | 
					    article: str
 | 
				
			||||||
 | 
					    client_id: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# region Requests
 | 
				
			||||||
 | 
					class ProductCreateRequest(CustomModel):
 | 
				
			||||||
 | 
					    name: str
 | 
				
			||||||
 | 
					    article: str
 | 
				
			||||||
 | 
					    client_id: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# region Responses
 | 
				
			||||||
 | 
					class ProductCreateResponse(CustomModel):
 | 
				
			||||||
 | 
					    product_id: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProductGetResponse(CustomModel):
 | 
				
			||||||
 | 
					    products: List[ProductSchema]
 | 
				
			||||||
 | 
					    pagination_info: PaginationInfoSchema
 | 
				
			||||||
 | 
					# endregion
 | 
				
			||||||
@@ -1,10 +1,11 @@
 | 
				
			|||||||
import datetime
 | 
					import models.secondary
 | 
				
			||||||
from typing import Type, Union
 | 
					from typing import Union
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from sqlalchemy import select
 | 
					from fastapi import HTTPException
 | 
				
			||||||
 | 
					from sqlalchemy import select, func
 | 
				
			||||||
from sqlalchemy.orm import joinedload, selectinload
 | 
					from sqlalchemy.orm import joinedload, selectinload
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from models import User, Deal
 | 
					from models import User, Service
 | 
				
			||||||
from models.deal import *
 | 
					from models.deal import *
 | 
				
			||||||
from schemas.client import ClientDetailsSchema
 | 
					from schemas.client import ClientDetailsSchema
 | 
				
			||||||
from schemas.deal import *
 | 
					from schemas.deal import *
 | 
				
			||||||
@@ -80,13 +81,27 @@ class DealService(BaseService):
 | 
				
			|||||||
        return DealChangeStatusResponse(ok=True)
 | 
					        return DealChangeStatusResponse(ok=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def get_summary(self) -> DealSummaryResponse:
 | 
					    async def get_summary(self) -> DealSummaryResponse:
 | 
				
			||||||
        deals_query = await self.session.scalars(select(Deal)
 | 
					        service_subquery = (
 | 
				
			||||||
                                                 .options(selectinload(Deal.status_history),
 | 
					            select(
 | 
				
			||||||
                                                          joinedload(Deal.client))
 | 
					                models.secondary.DealService.deal_id,
 | 
				
			||||||
                                                 .where(Deal.is_deleted == False,
 | 
					                func.sum(models.secondary.DealService.quantity * Service.price).label('total_price')
 | 
				
			||||||
                                                        Deal.is_completed == False))
 | 
					            )
 | 
				
			||||||
 | 
					            .join(Service)
 | 
				
			||||||
 | 
					            .group_by(models.secondary.DealService.deal_id)
 | 
				
			||||||
 | 
					            .subquery()
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        q = (select(
 | 
				
			||||||
 | 
					            Deal,
 | 
				
			||||||
 | 
					            func.coalesce(service_subquery.c.total_price, 0)
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					             .options(selectinload(Deal.status_history),
 | 
				
			||||||
 | 
					                      joinedload(Deal.client))
 | 
				
			||||||
 | 
					             .outerjoin(service_subquery, Deal.id == service_subquery.c.deal_id)
 | 
				
			||||||
 | 
					             .where(Deal.is_deleted == False,
 | 
				
			||||||
 | 
					                    Deal.is_completed == False))
 | 
				
			||||||
 | 
					        deals_query = await self.session.execute(q)
 | 
				
			||||||
        summaries = []
 | 
					        summaries = []
 | 
				
			||||||
        for deal in deals_query.all():
 | 
					        for deal, total_price in deals_query.all():
 | 
				
			||||||
            deal: Deal
 | 
					            deal: Deal
 | 
				
			||||||
            last_status: DealStatusHistory = max(deal.status_history, key=lambda status: status.changed_at)
 | 
					            last_status: DealStatusHistory = max(deal.status_history, key=lambda status: status.changed_at)
 | 
				
			||||||
            summaries.append(
 | 
					            summaries.append(
 | 
				
			||||||
@@ -95,7 +110,49 @@ class DealService(BaseService):
 | 
				
			|||||||
                    client_name=deal.client.name,
 | 
					                    client_name=deal.client.name,
 | 
				
			||||||
                    name=deal.name,
 | 
					                    name=deal.name,
 | 
				
			||||||
                    changed_at=last_status.changed_at,
 | 
					                    changed_at=last_status.changed_at,
 | 
				
			||||||
                    status=last_status.to_status
 | 
					                    status=last_status.to_status,
 | 
				
			||||||
 | 
					                    total_price=total_price
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        return DealSummaryResponse(summaries=summaries)
 | 
					        return DealSummaryResponse(summaries=summaries)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def add_services(self, request: DealAddServicesRequest):
 | 
				
			||||||
 | 
					        # TODO refactor
 | 
				
			||||||
 | 
					        deal: Deal = await self.session.scalar(
 | 
				
			||||||
 | 
					            select(Deal)
 | 
				
			||||||
 | 
					            .options(selectinload(Deal.services))
 | 
				
			||||||
 | 
					            .where(Deal.id == request.deal_id)
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        if not deal:
 | 
				
			||||||
 | 
					            raise HTTPException(status_code=404, detail="Deal is not found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        services_ids = [service.id for service in request.services]
 | 
				
			||||||
 | 
					        existing_service_ids = {service.service_id for service in deal.services}
 | 
				
			||||||
 | 
					        request_services_dict = {service.id: service.quantity for service in request.services}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        services_query = await self.session.scalars(select(Service).where(Service.id.in_(services_ids)))
 | 
				
			||||||
 | 
					        services = services_query.all()
 | 
				
			||||||
 | 
					        if len(services) != len(services_ids):
 | 
				
			||||||
 | 
					            raise HTTPException(status_code=404, detail="Some of services is not found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Adding quantity
 | 
				
			||||||
 | 
					        for deal_service in deal.services:
 | 
				
			||||||
 | 
					            deal_service: models.secondary.DealService
 | 
				
			||||||
 | 
					            if deal_service.service_id not in services_ids:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					            deal_service.quantity += request_services_dict[deal_service.service_id]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Adding new services
 | 
				
			||||||
 | 
					        for service in services:
 | 
				
			||||||
 | 
					            if service.id in existing_service_ids:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					            quantity = request_services_dict[service.id]
 | 
				
			||||||
 | 
					            deal.services.append(
 | 
				
			||||||
 | 
					                models.secondary.DealService(
 | 
				
			||||||
 | 
					                    service=service,
 | 
				
			||||||
 | 
					                    deal=deal,
 | 
				
			||||||
 | 
					                    quantity=quantity
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        await self.session.commit()
 | 
				
			||||||
 | 
					        return DealAddServicesResponse(ok=True, message='Услуги успешно добавлены')
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										37
									
								
								services/product.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								services/product.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					from fastapi import HTTPException
 | 
				
			||||||
 | 
					from sqlalchemy import select
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from models.product import Product
 | 
				
			||||||
 | 
					from schemas.base import PaginationSchema
 | 
				
			||||||
 | 
					from services.base import BaseService
 | 
				
			||||||
 | 
					from schemas.product import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProductService(BaseService):
 | 
				
			||||||
 | 
					    async def create(self, request: ProductCreateRequest) -> ProductCreateResponse:
 | 
				
			||||||
 | 
					        existing_product_query = await self.session.execute(
 | 
				
			||||||
 | 
					            select(Product)
 | 
				
			||||||
 | 
					            .where(Product.client_id == request.client_id,
 | 
				
			||||||
 | 
					                   Product.article == request.article)
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        existing_product = existing_product_query.first()
 | 
				
			||||||
 | 
					        if existing_product:
 | 
				
			||||||
 | 
					            raise HTTPException(status_code=403, detail="Product already exists")
 | 
				
			||||||
 | 
					        product = Product(**request.dict())
 | 
				
			||||||
 | 
					        self.session.add(product)
 | 
				
			||||||
 | 
					        await self.session.commit()
 | 
				
			||||||
 | 
					        return ProductCreateResponse(product_id=product.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def get_by_client_id(self, client_id: int, pagination: PaginationSchema) -> ProductGetResponse:
 | 
				
			||||||
 | 
					        query = await self.session.execute(
 | 
				
			||||||
 | 
					            select(Product)
 | 
				
			||||||
 | 
					            .where(Product.client_id == client_id)
 | 
				
			||||||
 | 
					            .offset(pagination.page * pagination.items_per_page)
 | 
				
			||||||
 | 
					            .limit(pagination.items_per_page)
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        products: list[ProductSchema] = []
 | 
				
			||||||
 | 
					        for product in query.scalars().all():
 | 
				
			||||||
 | 
					            products.append(
 | 
				
			||||||
 | 
					                ProductSchema.model_validate(product)
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        return ProductGetResponse(products=products)
 | 
				
			||||||
@@ -3,7 +3,7 @@ from sqlalchemy.orm import joinedload
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from models import Service, ServiceCategory
 | 
					from models import Service, ServiceCategory
 | 
				
			||||||
from services.base import BaseService
 | 
					from services.base import BaseService
 | 
				
			||||||
from schemas.services import ServiceGetAllResponse, ServiceSchema, ServiceGetAllCategoriesResponse, \
 | 
					from schemas.service import ServiceGetAllResponse, ServiceSchema, ServiceGetAllCategoriesResponse, \
 | 
				
			||||||
    ServiceCategorySchema, ServiceCreateRequest, ServiceCreateResponse, ServiceCreateCategoryRequest, \
 | 
					    ServiceCategorySchema, ServiceCreateRequest, ServiceCreateResponse, ServiceCreateCategoryRequest, \
 | 
				
			||||||
    ServiceCreateCategoryResponse
 | 
					    ServiceCreateCategoryResponse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								utils/dependecies.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								utils/dependecies.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					from schemas.base import PaginationSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def pagination_parameters(page: int, items_per_page: int) -> PaginationSchema:
 | 
				
			||||||
 | 
					    return PaginationSchema(page=page, items_per_page=items_per_page)
 | 
				
			||||||
		Reference in New Issue
	
	Block a user