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_id = Column(Integer, ForeignKey('clients.id'), nullable=False, comment='ID сделки')
 | 
				
			||||||
    client = relationship('Client', back_populates='products')
 | 
					    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):
 | 
					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_id = Column(Integer, ForeignKey('products.id'), nullable=False, comment='ID товара', primary_key=True)
 | 
				
			||||||
    product = relationship('Product', back_populates='barcodes')
 | 
					    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(
 | 
					@product_router.post(
 | 
				
			||||||
    '/create',
 | 
					    '/create',
 | 
				
			||||||
    response_model=ProductCreateResponse
 | 
					    response_model=ProductCreateResponse,
 | 
				
			||||||
 | 
					    operation_id='create_product'
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def create_product(
 | 
					async def create_product(
 | 
				
			||||||
        request: ProductCreateRequest,
 | 
					        request: ProductCreateRequest,
 | 
				
			||||||
@@ -26,6 +27,28 @@ async def create_product(
 | 
				
			|||||||
    return await ProductService(session).create(request)
 | 
					    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(
 | 
					@product_router.get(
 | 
				
			||||||
    '/get',
 | 
					    '/get',
 | 
				
			||||||
    response_model=ProductGetResponse,
 | 
					    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
 | 
					    auth_date: int
 | 
				
			||||||
    first_name: str
 | 
					    first_name: str
 | 
				
			||||||
    hash: str
 | 
					    hash: str
 | 
				
			||||||
@@ -9,5 +9,5 @@ class AuthLoginRequest(CustomModel):
 | 
				
			|||||||
    photo_url: str
 | 
					    photo_url: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AuthLoginResponse(CustomModel):
 | 
					class AuthLoginResponse(CustomModelCamel):
 | 
				
			||||||
    access_token: str
 | 
					    access_token: str
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
from pydantic import BaseModel
 | 
					from pydantic import BaseModel
 | 
				
			||||||
 | 
					from pydantic.alias_generators import to_camel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CustomConfig:
 | 
					class CustomConfig:
 | 
				
			||||||
@@ -6,21 +7,34 @@ class CustomConfig:
 | 
				
			|||||||
    from_attributes = True
 | 
					    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:
 | 
					    class Config:
 | 
				
			||||||
        from_attributes = True
 | 
					        from_attributes = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class OkMessageSchema(BaseModel):
 | 
					class OkMessageSchema(CustomModelCamel):
 | 
				
			||||||
    ok: bool
 | 
					    ok: bool
 | 
				
			||||||
    message: str
 | 
					    message: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PaginationSchema(CustomModel):
 | 
					class PaginationSchema(CustomModelCamel):
 | 
				
			||||||
    page: int
 | 
					    page: int
 | 
				
			||||||
    items_per_page: int
 | 
					    items_per_page: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PaginationInfoSchema(CustomModel):
 | 
					class PaginationInfoSchema(CustomModelCamel):
 | 
				
			||||||
    total_pages: int
 | 
					    total_pages: int
 | 
				
			||||||
    total_items: int
 | 
					    total_items: int
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,42 +1,42 @@
 | 
				
			|||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from schemas.base import CustomModel
 | 
					from schemas.base import CustomModelCamel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ClientDetailsSchema(CustomModel):
 | 
					class ClientDetailsSchema(CustomModelCamel):
 | 
				
			||||||
    address: str | None = None
 | 
					    address: str | None = None
 | 
				
			||||||
    phone_number: str | None = None
 | 
					    phone_number: str | None = None
 | 
				
			||||||
    inn: int | None = None
 | 
					    inn: int | None = None
 | 
				
			||||||
    email: str | None = None
 | 
					    email: str | None = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ClientSchema(CustomModel):
 | 
					class ClientSchema(CustomModelCamel):
 | 
				
			||||||
    id: int
 | 
					    id: int
 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
    details: ClientDetailsSchema | None = None
 | 
					    details: ClientDetailsSchema | None = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ClientSearchRequest(CustomModel):
 | 
					class ClientSearchRequest(CustomModelCamel):
 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ClientCreateRequest(CustomModel):
 | 
					class ClientCreateRequest(CustomModelCamel):
 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
    address: str
 | 
					    address: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ClientSearchResponse(CustomModel):
 | 
					class ClientSearchResponse(CustomModelCamel):
 | 
				
			||||||
    clients: List[ClientSchema]
 | 
					    clients: List[ClientSchema]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ClientUpdateDetailsRequest(CustomModel):
 | 
					class ClientUpdateDetailsRequest(CustomModelCamel):
 | 
				
			||||||
    client_id: int
 | 
					    client_id: int
 | 
				
			||||||
    details: ClientDetailsSchema
 | 
					    details: ClientDetailsSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ClientUpdateDetailsResponse(CustomModel):
 | 
					class ClientUpdateDetailsResponse(CustomModelCamel):
 | 
				
			||||||
    ok: bool
 | 
					    ok: bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ClientGetAllResponse(CustomModel):
 | 
					class ClientGetAllResponse(CustomModelCamel):
 | 
				
			||||||
    clients: List[ClientSchema]
 | 
					    clients: List[ClientSchema]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,19 +1,19 @@
 | 
				
			|||||||
import datetime
 | 
					import datetime
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from schemas.base import CustomModel
 | 
					from schemas.base import CustomModelCamel
 | 
				
			||||||
from schemas.client import ClientSchema
 | 
					from schemas.client import ClientSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# region Entities
 | 
					# region Entities
 | 
				
			||||||
class FastDeal(CustomModel):
 | 
					class FastDeal(CustomModelCamel):
 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
    client: ClientSchema
 | 
					    client: ClientSchema
 | 
				
			||||||
    comment: str
 | 
					    comment: str
 | 
				
			||||||
    acceptance_date: datetime.datetime
 | 
					    acceptance_date: datetime.datetime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealSummary(CustomModel):
 | 
					class DealSummary(CustomModelCamel):
 | 
				
			||||||
    id: int
 | 
					    id: int
 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
    client_name: str
 | 
					    client_name: str
 | 
				
			||||||
@@ -22,7 +22,7 @@ class DealSummary(CustomModel):
 | 
				
			|||||||
    total_price: int
 | 
					    total_price: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealServiceSchema(CustomModel):
 | 
					class DealServiceSchema(CustomModelCamel):
 | 
				
			||||||
    id: int
 | 
					    id: int
 | 
				
			||||||
    quantity: int
 | 
					    quantity: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -30,16 +30,16 @@ class DealServiceSchema(CustomModel):
 | 
				
			|||||||
# endregion Entities
 | 
					# endregion Entities
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# region Requests
 | 
					# region Requests
 | 
				
			||||||
class DealChangeStatusRequest(CustomModel):
 | 
					class DealChangeStatusRequest(CustomModelCamel):
 | 
				
			||||||
    deal_id: int
 | 
					    deal_id: int
 | 
				
			||||||
    new_status: int
 | 
					    new_status: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealCreateRequest(CustomModel):
 | 
					class DealCreateRequest(CustomModelCamel):
 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealQuickCreateRequest(CustomModel):
 | 
					class DealQuickCreateRequest(CustomModelCamel):
 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
    client_name: str
 | 
					    client_name: str
 | 
				
			||||||
    client_address: str
 | 
					    client_address: str
 | 
				
			||||||
@@ -47,11 +47,11 @@ class DealQuickCreateRequest(CustomModel):
 | 
				
			|||||||
    acceptance_date: datetime.datetime
 | 
					    acceptance_date: datetime.datetime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealSummaryRequest(CustomModel):
 | 
					class DealSummaryRequest(CustomModelCamel):
 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealAddServicesRequest(CustomModel):
 | 
					class DealAddServicesRequest(CustomModelCamel):
 | 
				
			||||||
    deal_id: int
 | 
					    deal_id: int
 | 
				
			||||||
    services: list[DealServiceSchema]
 | 
					    services: list[DealServiceSchema]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -60,23 +60,23 @@ class DealAddServicesRequest(CustomModel):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# region Responses
 | 
					# region Responses
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealChangeStatusResponse(CustomModel):
 | 
					class DealChangeStatusResponse(CustomModelCamel):
 | 
				
			||||||
    ok: bool
 | 
					    ok: bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealCreateResponse(CustomModel):
 | 
					class DealCreateResponse(CustomModelCamel):
 | 
				
			||||||
    ok: bool
 | 
					    ok: bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealQuickCreateResponse(CustomModel):
 | 
					class DealQuickCreateResponse(CustomModelCamel):
 | 
				
			||||||
    deal_id: int
 | 
					    deal_id: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealSummaryResponse(CustomModel):
 | 
					class DealSummaryResponse(CustomModelCamel):
 | 
				
			||||||
    summaries: List[DealSummary]
 | 
					    summaries: List[DealSummary]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealAddServicesResponse(CustomModel):
 | 
					class DealAddServicesResponse(CustomModelCamel):
 | 
				
			||||||
    ok: bool
 | 
					    ok: bool
 | 
				
			||||||
    message: str
 | 
					    message: str
 | 
				
			||||||
# endregion Responses
 | 
					# endregion Responses
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,33 +1,51 @@
 | 
				
			|||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from schemas.base import CustomModel, PaginationInfoSchema
 | 
					from schemas.base import CustomModelCamel, PaginationInfoSchema, OkMessageSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# region Entities
 | 
					# region Entities
 | 
				
			||||||
class ProductSchema(CustomModel):
 | 
					class ProductSchema(CustomModelCamel):
 | 
				
			||||||
    id: int
 | 
					    id: int
 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
    article: str
 | 
					    article: str
 | 
				
			||||||
    client_id: int
 | 
					    client_id: int
 | 
				
			||||||
 | 
					    barcodes: list[str]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# endregion
 | 
					# endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# region Requests
 | 
					# region Requests
 | 
				
			||||||
class ProductCreateRequest(CustomModel):
 | 
					class ProductCreateRequest(CustomModelCamel):
 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
    article: str
 | 
					    article: str
 | 
				
			||||||
    client_id: int
 | 
					    client_id: int
 | 
				
			||||||
 | 
					    barcodes: List[str]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProductDeleteRequest(CustomModelCamel):
 | 
				
			||||||
 | 
					    product_id: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProductUpdateRequest(CustomModelCamel):
 | 
				
			||||||
 | 
					    product: ProductSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# endregion
 | 
					# endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# region Responses
 | 
					# region Responses
 | 
				
			||||||
class ProductCreateResponse(CustomModel):
 | 
					class ProductCreateResponse(OkMessageSchema):
 | 
				
			||||||
    product_id: int
 | 
					    product_id: int | None = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ProductGetResponse(CustomModel):
 | 
					class ProductGetResponse(CustomModelCamel):
 | 
				
			||||||
    products: List[ProductSchema]
 | 
					    products: List[ProductSchema]
 | 
				
			||||||
    pagination_info: PaginationInfoSchema
 | 
					    pagination_info: PaginationInfoSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProductDeleteResponse(OkMessageSchema):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProductUpdateResponse(OkMessageSchema):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
# endregion
 | 
					# endregion
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,15 +1,15 @@
 | 
				
			|||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from schemas.base import CustomModel, OkMessageSchema
 | 
					from schemas.base import CustomModelCamel, OkMessageSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# region Entities
 | 
					# region Entities
 | 
				
			||||||
class ServiceCategorySchema(CustomModel):
 | 
					class ServiceCategorySchema(CustomModelCamel):
 | 
				
			||||||
    id: int
 | 
					    id: int
 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ServiceSchema(CustomModel):
 | 
					class ServiceSchema(CustomModelCamel):
 | 
				
			||||||
    id: int
 | 
					    id: int
 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
    category: ServiceCategorySchema
 | 
					    category: ServiceCategorySchema
 | 
				
			||||||
@@ -20,11 +20,11 @@ class ServiceSchema(CustomModel):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# region Requests
 | 
					# region Requests
 | 
				
			||||||
class ServiceCreateRequest(CustomModel):
 | 
					class ServiceCreateRequest(CustomModelCamel):
 | 
				
			||||||
    service: ServiceSchema
 | 
					    service: ServiceSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ServiceCreateCategoryRequest(CustomModel):
 | 
					class ServiceCreateCategoryRequest(CustomModelCamel):
 | 
				
			||||||
    category: ServiceCategorySchema
 | 
					    category: ServiceCategorySchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -32,11 +32,11 @@ class ServiceCreateCategoryRequest(CustomModel):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# region Responses
 | 
					# region Responses
 | 
				
			||||||
class ServiceGetAllResponse(CustomModel):
 | 
					class ServiceGetAllResponse(CustomModelCamel):
 | 
				
			||||||
    services: List[ServiceSchema]
 | 
					    services: List[ServiceSchema]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ServiceGetAllCategoriesResponse(CustomModel):
 | 
					class ServiceGetAllCategoriesResponse(CustomModelCamel):
 | 
				
			||||||
    categories: List[ServiceCategorySchema]
 | 
					    categories: List[ServiceCategorySchema]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
from typing import Union, Annotated
 | 
					from typing import Union, Annotated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from fastapi import Depends, HTTPException
 | 
					from fastapi import Depends, HTTPException
 | 
				
			||||||
from fastapi.security import OAuth2PasswordBearer, HTTPBearer, HTTPAuthorizationCredentials
 | 
					from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
 | 
				
			||||||
from jose import jwt, JWTError
 | 
					from jose import jwt, JWTError
 | 
				
			||||||
from sqlalchemy import select
 | 
					from sqlalchemy import select
 | 
				
			||||||
from sqlalchemy.ext.asyncio import AsyncSession
 | 
					from sqlalchemy.ext.asyncio import AsyncSession
 | 
				
			||||||
@@ -10,8 +10,8 @@ from starlette import status
 | 
				
			|||||||
import backend.config
 | 
					import backend.config
 | 
				
			||||||
from backend.session import get_session
 | 
					from backend.session import get_session
 | 
				
			||||||
from models import User
 | 
					from models import User
 | 
				
			||||||
from services.base import BaseService
 | 
					 | 
				
			||||||
from schemas.auth import *
 | 
					from schemas.auth import *
 | 
				
			||||||
 | 
					from services.base import BaseService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
oauth2_schema = HTTPBearer()
 | 
					oauth2_schema = HTTPBearer()
 | 
				
			||||||
algorithm = 'HS256'
 | 
					algorithm = 'HS256'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,8 @@
 | 
				
			|||||||
from fastapi import HTTPException
 | 
					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 schemas.base import PaginationSchema
 | 
				
			||||||
from services.base import BaseService
 | 
					from services.base import BaseService
 | 
				
			||||||
from schemas.product import *
 | 
					from schemas.product import *
 | 
				
			||||||
@@ -9,6 +10,7 @@ from schemas.product import *
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class ProductService(BaseService):
 | 
					class ProductService(BaseService):
 | 
				
			||||||
    async def create(self, request: ProductCreateRequest) -> ProductCreateResponse:
 | 
					    async def create(self, request: ProductCreateRequest) -> ProductCreateResponse:
 | 
				
			||||||
 | 
					        # Unique article validation
 | 
				
			||||||
        existing_product_query = await self.session.execute(
 | 
					        existing_product_query = await self.session.execute(
 | 
				
			||||||
            select(Product)
 | 
					            select(Product)
 | 
				
			||||||
            .where(Product.client_id == request.client_id,
 | 
					            .where(Product.client_id == request.client_id,
 | 
				
			||||||
@@ -16,22 +18,101 @@ class ProductService(BaseService):
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
        existing_product = existing_product_query.first()
 | 
					        existing_product = existing_product_query.first()
 | 
				
			||||||
        if existing_product:
 | 
					        if existing_product:
 | 
				
			||||||
            raise HTTPException(status_code=403, detail="Product already exists")
 | 
					            return ProductCreateResponse(ok=False, message='Товар с таким артикулом уже существует у клиента')
 | 
				
			||||||
        product = Product(**request.dict())
 | 
					
 | 
				
			||||||
 | 
					        # Creating product
 | 
				
			||||||
 | 
					        product_dict = request.dict()
 | 
				
			||||||
 | 
					        del product_dict['barcodes']
 | 
				
			||||||
 | 
					        product = Product(**product_dict)
 | 
				
			||||||
        self.session.add(product)
 | 
					        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()
 | 
					        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:
 | 
					    async def get_by_client_id(self, client_id: int, pagination: PaginationSchema) -> ProductGetResponse:
 | 
				
			||||||
        query = await self.session.execute(
 | 
					        stmt = (
 | 
				
			||||||
            select(Product)
 | 
					            select(Product)
 | 
				
			||||||
 | 
					            .options(selectinload(Product.barcodes))
 | 
				
			||||||
            .where(Product.client_id == client_id)
 | 
					            .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)
 | 
					            .offset(pagination.page * pagination.items_per_page)
 | 
				
			||||||
            .limit(pagination.items_per_page)
 | 
					            .limit(pagination.items_per_page)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        products: list[ProductSchema] = []
 | 
					        products: list[ProductSchema] = []
 | 
				
			||||||
        for product in query.scalars().all():
 | 
					        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(
 | 
					            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