crappy
This commit is contained in:
		@@ -12,7 +12,7 @@ class Product(BaseModel):
 | 
			
		||||
 | 
			
		||||
    client_id = Column(Integer, ForeignKey('clients.id'), nullable=False, comment='ID сделки')
 | 
			
		||||
    client = relationship('Client', back_populates='products')
 | 
			
		||||
    barcodes = relationship('ProductBarcode', back_populates='product')
 | 
			
		||||
    barcodes = relationship('ProductBarcode', back_populates='product', cascade="all, delete-orphan")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ProductBarcode(BaseModel):
 | 
			
		||||
@@ -20,4 +20,4 @@ class ProductBarcode(BaseModel):
 | 
			
		||||
    product_id = Column(Integer, ForeignKey('products.id'), nullable=False, comment='ID товара', primary_key=True)
 | 
			
		||||
    product = relationship('Product', back_populates='barcodes')
 | 
			
		||||
 | 
			
		||||
    barcode = Column(String, nullable=False, index=True, comment='ШК товара')
 | 
			
		||||
    barcode = Column(String, nullable=False, index=True, comment='ШК товара', primary_key=True)
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,8 @@ product_router = APIRouter(
 | 
			
		||||
 | 
			
		||||
@product_router.post(
 | 
			
		||||
    '/create',
 | 
			
		||||
    response_model=ProductCreateResponse
 | 
			
		||||
    response_model=ProductCreateResponse,
 | 
			
		||||
    operation_id='create_product'
 | 
			
		||||
)
 | 
			
		||||
async def create_product(
 | 
			
		||||
        request: ProductCreateRequest,
 | 
			
		||||
@@ -26,6 +27,28 @@ async def create_product(
 | 
			
		||||
    return await ProductService(session).create(request)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@product_router.post(
 | 
			
		||||
    '/delete',
 | 
			
		||||
    response_model=ProductDeleteResponse,
 | 
			
		||||
    operation_id='delete_product'
 | 
			
		||||
)
 | 
			
		||||
async def delete_product(
 | 
			
		||||
        request: ProductDeleteRequest,
 | 
			
		||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
			
		||||
):
 | 
			
		||||
    return await ProductService(session).delete(request)
 | 
			
		||||
 | 
			
		||||
@product_router.post(
 | 
			
		||||
    '/update',
 | 
			
		||||
    response_model=ProductUpdateResponse,
 | 
			
		||||
    operation_id='update_product'
 | 
			
		||||
)
 | 
			
		||||
async def delete_product(
 | 
			
		||||
        request: ProductUpdateRequest,
 | 
			
		||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
			
		||||
):
 | 
			
		||||
    return await ProductService(session).update(request)
 | 
			
		||||
 | 
			
		||||
@product_router.get(
 | 
			
		||||
    '/get',
 | 
			
		||||
    response_model=ProductGetResponse,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
from schemas.base import CustomModel
 | 
			
		||||
from schemas.base import CustomModelCamel, CustomModelSnake
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthLoginRequest(CustomModel):
 | 
			
		||||
class AuthLoginRequest(CustomModelSnake):
 | 
			
		||||
    auth_date: int
 | 
			
		||||
    first_name: str
 | 
			
		||||
    hash: str
 | 
			
		||||
@@ -9,5 +9,5 @@ class AuthLoginRequest(CustomModel):
 | 
			
		||||
    photo_url: str
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthLoginResponse(CustomModel):
 | 
			
		||||
class AuthLoginResponse(CustomModelCamel):
 | 
			
		||||
    access_token: str
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
from pydantic import BaseModel
 | 
			
		||||
from pydantic.alias_generators import to_camel
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CustomConfig:
 | 
			
		||||
@@ -6,21 +7,34 @@ class CustomConfig:
 | 
			
		||||
    from_attributes = True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CustomModel(BaseModel):
 | 
			
		||||
class CustomModelCamel(BaseModel):
 | 
			
		||||
    class Config:
 | 
			
		||||
        from_attributes = True
 | 
			
		||||
        alias_generator = to_camel
 | 
			
		||||
        populate_by_name = True
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def from_sql_model(cls, model, fields: dict):
 | 
			
		||||
        model_dict = {c.name: getattr(model, c.name) for c in model.__table__.columns}
 | 
			
		||||
        model_dict.update(fields)
 | 
			
		||||
        return cls(**model_dict)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CustomModelSnake(BaseModel):
 | 
			
		||||
    class Config:
 | 
			
		||||
        from_attributes = True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OkMessageSchema(BaseModel):
 | 
			
		||||
class OkMessageSchema(CustomModelCamel):
 | 
			
		||||
    ok: bool
 | 
			
		||||
    message: str
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PaginationSchema(CustomModel):
 | 
			
		||||
class PaginationSchema(CustomModelCamel):
 | 
			
		||||
    page: int
 | 
			
		||||
    items_per_page: int
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PaginationInfoSchema(CustomModel):
 | 
			
		||||
class PaginationInfoSchema(CustomModelCamel):
 | 
			
		||||
    total_pages: int
 | 
			
		||||
    total_items: int
 | 
			
		||||
 
 | 
			
		||||
@@ -1,42 +1,42 @@
 | 
			
		||||
from typing import List
 | 
			
		||||
 | 
			
		||||
from schemas.base import CustomModel
 | 
			
		||||
from schemas.base import CustomModelCamel
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClientDetailsSchema(CustomModel):
 | 
			
		||||
class ClientDetailsSchema(CustomModelCamel):
 | 
			
		||||
    address: str | None = None
 | 
			
		||||
    phone_number: str | None = None
 | 
			
		||||
    inn: int | None = None
 | 
			
		||||
    email: str | None = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClientSchema(CustomModel):
 | 
			
		||||
class ClientSchema(CustomModelCamel):
 | 
			
		||||
    id: int
 | 
			
		||||
    name: str
 | 
			
		||||
    details: ClientDetailsSchema | None = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClientSearchRequest(CustomModel):
 | 
			
		||||
class ClientSearchRequest(CustomModelCamel):
 | 
			
		||||
    name: str
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClientCreateRequest(CustomModel):
 | 
			
		||||
class ClientCreateRequest(CustomModelCamel):
 | 
			
		||||
    name: str
 | 
			
		||||
    address: str
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClientSearchResponse(CustomModel):
 | 
			
		||||
class ClientSearchResponse(CustomModelCamel):
 | 
			
		||||
    clients: List[ClientSchema]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClientUpdateDetailsRequest(CustomModel):
 | 
			
		||||
class ClientUpdateDetailsRequest(CustomModelCamel):
 | 
			
		||||
    client_id: int
 | 
			
		||||
    details: ClientDetailsSchema
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClientUpdateDetailsResponse(CustomModel):
 | 
			
		||||
class ClientUpdateDetailsResponse(CustomModelCamel):
 | 
			
		||||
    ok: bool
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClientGetAllResponse(CustomModel):
 | 
			
		||||
class ClientGetAllResponse(CustomModelCamel):
 | 
			
		||||
    clients: List[ClientSchema]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,19 @@
 | 
			
		||||
import datetime
 | 
			
		||||
from typing import List
 | 
			
		||||
 | 
			
		||||
from schemas.base import CustomModel
 | 
			
		||||
from schemas.base import CustomModelCamel
 | 
			
		||||
from schemas.client import ClientSchema
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# region Entities
 | 
			
		||||
class FastDeal(CustomModel):
 | 
			
		||||
class FastDeal(CustomModelCamel):
 | 
			
		||||
    name: str
 | 
			
		||||
    client: ClientSchema
 | 
			
		||||
    comment: str
 | 
			
		||||
    acceptance_date: datetime.datetime
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealSummary(CustomModel):
 | 
			
		||||
class DealSummary(CustomModelCamel):
 | 
			
		||||
    id: int
 | 
			
		||||
    name: str
 | 
			
		||||
    client_name: str
 | 
			
		||||
@@ -22,7 +22,7 @@ class DealSummary(CustomModel):
 | 
			
		||||
    total_price: int
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealServiceSchema(CustomModel):
 | 
			
		||||
class DealServiceSchema(CustomModelCamel):
 | 
			
		||||
    id: int
 | 
			
		||||
    quantity: int
 | 
			
		||||
 | 
			
		||||
@@ -30,16 +30,16 @@ class DealServiceSchema(CustomModel):
 | 
			
		||||
# endregion Entities
 | 
			
		||||
 | 
			
		||||
# region Requests
 | 
			
		||||
class DealChangeStatusRequest(CustomModel):
 | 
			
		||||
class DealChangeStatusRequest(CustomModelCamel):
 | 
			
		||||
    deal_id: int
 | 
			
		||||
    new_status: int
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealCreateRequest(CustomModel):
 | 
			
		||||
class DealCreateRequest(CustomModelCamel):
 | 
			
		||||
    name: str
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealQuickCreateRequest(CustomModel):
 | 
			
		||||
class DealQuickCreateRequest(CustomModelCamel):
 | 
			
		||||
    name: str
 | 
			
		||||
    client_name: str
 | 
			
		||||
    client_address: str
 | 
			
		||||
@@ -47,11 +47,11 @@ class DealQuickCreateRequest(CustomModel):
 | 
			
		||||
    acceptance_date: datetime.datetime
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealSummaryRequest(CustomModel):
 | 
			
		||||
class DealSummaryRequest(CustomModelCamel):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealAddServicesRequest(CustomModel):
 | 
			
		||||
class DealAddServicesRequest(CustomModelCamel):
 | 
			
		||||
    deal_id: int
 | 
			
		||||
    services: list[DealServiceSchema]
 | 
			
		||||
 | 
			
		||||
@@ -60,23 +60,23 @@ class DealAddServicesRequest(CustomModel):
 | 
			
		||||
 | 
			
		||||
# region Responses
 | 
			
		||||
 | 
			
		||||
class DealChangeStatusResponse(CustomModel):
 | 
			
		||||
class DealChangeStatusResponse(CustomModelCamel):
 | 
			
		||||
    ok: bool
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealCreateResponse(CustomModel):
 | 
			
		||||
class DealCreateResponse(CustomModelCamel):
 | 
			
		||||
    ok: bool
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealQuickCreateResponse(CustomModel):
 | 
			
		||||
class DealQuickCreateResponse(CustomModelCamel):
 | 
			
		||||
    deal_id: int
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealSummaryResponse(CustomModel):
 | 
			
		||||
class DealSummaryResponse(CustomModelCamel):
 | 
			
		||||
    summaries: List[DealSummary]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DealAddServicesResponse(CustomModel):
 | 
			
		||||
class DealAddServicesResponse(CustomModelCamel):
 | 
			
		||||
    ok: bool
 | 
			
		||||
    message: str
 | 
			
		||||
# endregion Responses
 | 
			
		||||
 
 | 
			
		||||
@@ -1,33 +1,51 @@
 | 
			
		||||
from typing import List
 | 
			
		||||
 | 
			
		||||
from schemas.base import CustomModel, PaginationInfoSchema
 | 
			
		||||
from schemas.base import CustomModelCamel, PaginationInfoSchema, OkMessageSchema
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# region Entities
 | 
			
		||||
class ProductSchema(CustomModel):
 | 
			
		||||
class ProductSchema(CustomModelCamel):
 | 
			
		||||
    id: int
 | 
			
		||||
    name: str
 | 
			
		||||
    article: str
 | 
			
		||||
    client_id: int
 | 
			
		||||
    barcodes: list[str]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# endregion
 | 
			
		||||
 | 
			
		||||
# region Requests
 | 
			
		||||
class ProductCreateRequest(CustomModel):
 | 
			
		||||
class ProductCreateRequest(CustomModelCamel):
 | 
			
		||||
    name: str
 | 
			
		||||
    article: str
 | 
			
		||||
    client_id: int
 | 
			
		||||
    barcodes: List[str]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ProductDeleteRequest(CustomModelCamel):
 | 
			
		||||
    product_id: int
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ProductUpdateRequest(CustomModelCamel):
 | 
			
		||||
    product: ProductSchema
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# endregion
 | 
			
		||||
 | 
			
		||||
# region Responses
 | 
			
		||||
class ProductCreateResponse(CustomModel):
 | 
			
		||||
    product_id: int
 | 
			
		||||
class ProductCreateResponse(OkMessageSchema):
 | 
			
		||||
    product_id: int | None = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ProductGetResponse(CustomModel):
 | 
			
		||||
class ProductGetResponse(CustomModelCamel):
 | 
			
		||||
    products: List[ProductSchema]
 | 
			
		||||
    pagination_info: PaginationInfoSchema
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ProductDeleteResponse(OkMessageSchema):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ProductUpdateResponse(OkMessageSchema):
 | 
			
		||||
    pass
 | 
			
		||||
# endregion
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,15 @@
 | 
			
		||||
from typing import List
 | 
			
		||||
 | 
			
		||||
from schemas.base import CustomModel, OkMessageSchema
 | 
			
		||||
from schemas.base import CustomModelCamel, OkMessageSchema
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# region Entities
 | 
			
		||||
class ServiceCategorySchema(CustomModel):
 | 
			
		||||
class ServiceCategorySchema(CustomModelCamel):
 | 
			
		||||
    id: int
 | 
			
		||||
    name: str
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ServiceSchema(CustomModel):
 | 
			
		||||
class ServiceSchema(CustomModelCamel):
 | 
			
		||||
    id: int
 | 
			
		||||
    name: str
 | 
			
		||||
    category: ServiceCategorySchema
 | 
			
		||||
@@ -20,11 +20,11 @@ class ServiceSchema(CustomModel):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# region Requests
 | 
			
		||||
class ServiceCreateRequest(CustomModel):
 | 
			
		||||
class ServiceCreateRequest(CustomModelCamel):
 | 
			
		||||
    service: ServiceSchema
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ServiceCreateCategoryRequest(CustomModel):
 | 
			
		||||
class ServiceCreateCategoryRequest(CustomModelCamel):
 | 
			
		||||
    category: ServiceCategorySchema
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -32,11 +32,11 @@ class ServiceCreateCategoryRequest(CustomModel):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# region Responses
 | 
			
		||||
class ServiceGetAllResponse(CustomModel):
 | 
			
		||||
class ServiceGetAllResponse(CustomModelCamel):
 | 
			
		||||
    services: List[ServiceSchema]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ServiceGetAllCategoriesResponse(CustomModel):
 | 
			
		||||
class ServiceGetAllCategoriesResponse(CustomModelCamel):
 | 
			
		||||
    categories: List[ServiceCategorySchema]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
from typing import Union, Annotated
 | 
			
		||||
 | 
			
		||||
from fastapi import Depends, HTTPException
 | 
			
		||||
from fastapi.security import OAuth2PasswordBearer, HTTPBearer, HTTPAuthorizationCredentials
 | 
			
		||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
 | 
			
		||||
from jose import jwt, JWTError
 | 
			
		||||
from sqlalchemy import select
 | 
			
		||||
from sqlalchemy.ext.asyncio import AsyncSession
 | 
			
		||||
@@ -10,8 +10,8 @@ from starlette import status
 | 
			
		||||
import backend.config
 | 
			
		||||
from backend.session import get_session
 | 
			
		||||
from models import User
 | 
			
		||||
from services.base import BaseService
 | 
			
		||||
from schemas.auth import *
 | 
			
		||||
from services.base import BaseService
 | 
			
		||||
 | 
			
		||||
oauth2_schema = HTTPBearer()
 | 
			
		||||
algorithm = 'HS256'
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
from fastapi import HTTPException
 | 
			
		||||
from sqlalchemy import select
 | 
			
		||||
from sqlalchemy import select, func, Integer, update
 | 
			
		||||
from sqlalchemy.orm import selectinload
 | 
			
		||||
 | 
			
		||||
from models.product import Product
 | 
			
		||||
from models.product import Product, ProductBarcode
 | 
			
		||||
from schemas.base import PaginationSchema
 | 
			
		||||
from services.base import BaseService
 | 
			
		||||
from schemas.product import *
 | 
			
		||||
@@ -9,6 +10,7 @@ from schemas.product import *
 | 
			
		||||
 | 
			
		||||
class ProductService(BaseService):
 | 
			
		||||
    async def create(self, request: ProductCreateRequest) -> ProductCreateResponse:
 | 
			
		||||
        # Unique article validation
 | 
			
		||||
        existing_product_query = await self.session.execute(
 | 
			
		||||
            select(Product)
 | 
			
		||||
            .where(Product.client_id == request.client_id,
 | 
			
		||||
@@ -16,22 +18,101 @@ class ProductService(BaseService):
 | 
			
		||||
        )
 | 
			
		||||
        existing_product = existing_product_query.first()
 | 
			
		||||
        if existing_product:
 | 
			
		||||
            raise HTTPException(status_code=403, detail="Product already exists")
 | 
			
		||||
        product = Product(**request.dict())
 | 
			
		||||
            return ProductCreateResponse(ok=False, message='Товар с таким артикулом уже существует у клиента')
 | 
			
		||||
 | 
			
		||||
        # Creating product
 | 
			
		||||
        product_dict = request.dict()
 | 
			
		||||
        del product_dict['barcodes']
 | 
			
		||||
        product = Product(**product_dict)
 | 
			
		||||
        self.session.add(product)
 | 
			
		||||
 | 
			
		||||
        # Creating barcodes
 | 
			
		||||
        await self.session.flush()
 | 
			
		||||
        for barcode in request.barcodes:
 | 
			
		||||
            product_barcode = ProductBarcode(product_id=product.id,
 | 
			
		||||
                                             barcode=barcode)
 | 
			
		||||
            self.session.add(product_barcode)
 | 
			
		||||
            await self.session.flush()
 | 
			
		||||
        await self.session.commit()
 | 
			
		||||
        return ProductCreateResponse(product_id=product.id)
 | 
			
		||||
        return ProductCreateResponse(ok=True, message='Товар успешно создан', product_id=product.id)
 | 
			
		||||
 | 
			
		||||
    async def delete(self, request: ProductDeleteRequest):
 | 
			
		||||
        product = await self.session.get(Product, request.product_id)
 | 
			
		||||
        if not product:
 | 
			
		||||
            return ProductDeleteResponse(ok=False, message='Указанного товара не существует')
 | 
			
		||||
        await self.session.delete(product)
 | 
			
		||||
        await self.session.commit()
 | 
			
		||||
        return ProductDeleteResponse(ok=True, message="Товар успешно удален!")
 | 
			
		||||
 | 
			
		||||
    async def update(self, request: ProductUpdateRequest):
 | 
			
		||||
        stmt = (
 | 
			
		||||
            select(Product)
 | 
			
		||||
            .where(Product.id == request.product.id)
 | 
			
		||||
            .options(selectinload(Product.barcodes))
 | 
			
		||||
        )
 | 
			
		||||
        product_query = await self.session.execute(stmt)
 | 
			
		||||
        product = product_query.scalar()
 | 
			
		||||
        if not product:
 | 
			
		||||
            return ProductUpdateResponse(ok=False, message='Указанного товара не существует')
 | 
			
		||||
        product_dict = request.product.dict()
 | 
			
		||||
        del product_dict['id']
 | 
			
		||||
        del product_dict['barcodes']
 | 
			
		||||
        await self.session.execute(
 | 
			
		||||
            update(Product)
 | 
			
		||||
            .where(Product.id == request.product.id)
 | 
			
		||||
            .values(**product_dict)
 | 
			
		||||
        )
 | 
			
		||||
        # Updating barcodes
 | 
			
		||||
        product_barcodes = set([barcode for barcode in product.barcodes])
 | 
			
		||||
        request_barcodes = set(request.product.barcodes)
 | 
			
		||||
        new_barcodes = request_barcodes.difference(product_barcodes)
 | 
			
		||||
        deleted_barcodes = product_barcodes.difference(request_barcodes)
 | 
			
		||||
        for product_barcode in product.barcodes:
 | 
			
		||||
            if product_barcode not in deleted_barcodes:
 | 
			
		||||
                continue
 | 
			
		||||
            await self.session.delete(product_barcode)
 | 
			
		||||
        for new_barcode in new_barcodes:
 | 
			
		||||
            product_barcode = ProductBarcode(
 | 
			
		||||
                product_id=product.id,
 | 
			
		||||
                barcode=new_barcode
 | 
			
		||||
            )
 | 
			
		||||
            self.session.add(product_barcode)
 | 
			
		||||
            await self.session.flush()
 | 
			
		||||
 | 
			
		||||
        await self.session.commit()
 | 
			
		||||
        return ProductUpdateResponse(ok=True, message='Товар успешно обновлен')
 | 
			
		||||
 | 
			
		||||
    async def get_by_client_id(self, client_id: int, pagination: PaginationSchema) -> ProductGetResponse:
 | 
			
		||||
        query = await self.session.execute(
 | 
			
		||||
        stmt = (
 | 
			
		||||
            select(Product)
 | 
			
		||||
            .options(selectinload(Product.barcodes))
 | 
			
		||||
            .where(Product.client_id == client_id)
 | 
			
		||||
            .order_by(Product.id)
 | 
			
		||||
        )
 | 
			
		||||
        total_products_query = await self.session.execute(
 | 
			
		||||
            select(
 | 
			
		||||
                func.cast(func.ceil(func.count() / pagination.items_per_page), Integer),
 | 
			
		||||
                func.count()
 | 
			
		||||
            )
 | 
			
		||||
            .select_from(stmt.subquery())
 | 
			
		||||
        )
 | 
			
		||||
        total_pages, total_items = total_products_query.first()
 | 
			
		||||
        pagination_info = PaginationInfoSchema(total_pages=total_pages, total_items=total_items)
 | 
			
		||||
        query = await self.session.execute(
 | 
			
		||||
            stmt
 | 
			
		||||
            .offset(pagination.page * pagination.items_per_page)
 | 
			
		||||
            .limit(pagination.items_per_page)
 | 
			
		||||
        )
 | 
			
		||||
        products: list[ProductSchema] = []
 | 
			
		||||
        for product in query.scalars().all():
 | 
			
		||||
            product: Product
 | 
			
		||||
 | 
			
		||||
            barcodes = []
 | 
			
		||||
            for barcode_obj in product.barcodes:
 | 
			
		||||
                barcode_obj: ProductBarcode
 | 
			
		||||
                barcodes.append(barcode_obj.barcode)
 | 
			
		||||
 | 
			
		||||
            products.append(
 | 
			
		||||
                ProductSchema.model_validate(product)
 | 
			
		||||
                ProductSchema.from_sql_model(product, {'barcodes': barcodes})
 | 
			
		||||
            )
 | 
			
		||||
        return ProductGetResponse(products=products)
 | 
			
		||||
        return ProductGetResponse(products=products, pagination_info=pagination_info)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1241
									
								
								test/test.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1241
									
								
								test/test.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										36
									
								
								test/test.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								test/test.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
import asyncio
 | 
			
		||||
 | 
			
		||||
from sqlalchemy.ext.asyncio import AsyncSession
 | 
			
		||||
 | 
			
		||||
from backend.session import session_maker
 | 
			
		||||
from models import Product, ProductBarcode
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def main(session: AsyncSession):
 | 
			
		||||
    client_ids = [2, 4]
 | 
			
		||||
    for client_id in client_ids:
 | 
			
		||||
        for i in range(1, 500 + 1):
 | 
			
		||||
            product = Product(
 | 
			
		||||
                name=f"Товар №{i}",
 | 
			
		||||
                article=f"Ариткул товара №{i}",
 | 
			
		||||
                client_id=client_id
 | 
			
		||||
            )
 | 
			
		||||
            session.add(product)
 | 
			
		||||
            await session.flush()
 | 
			
		||||
            for j in range(1, 5 + 1):
 | 
			
		||||
                barcode = ProductBarcode(
 | 
			
		||||
                    barcode=f"Штрихкод №{j} для товара №{i}",
 | 
			
		||||
                    product_id=product.id
 | 
			
		||||
                )
 | 
			
		||||
                session.add(barcode)
 | 
			
		||||
            await session.flush()
 | 
			
		||||
    await session.commit()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def preload():
 | 
			
		||||
    async with session_maker() as session:
 | 
			
		||||
        await main(session)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    asyncio.run(preload())
 | 
			
		||||
		Reference in New Issue
	
	Block a user