This commit is contained in:
2024-04-12 07:34:21 +03:00
parent 5c81af05d5
commit be623a3555
12 changed files with 513 additions and 93 deletions

View File

@@ -2,6 +2,7 @@ from fastapi import HTTPException
from sqlalchemy import select, func, Integer, update
from sqlalchemy.orm import selectinload
import utils.barcodes
from models.product import Product, ProductBarcode
from schemas.base import PaginationSchema
from services.base import BaseService
@@ -85,6 +86,9 @@ class ProductService(BaseService):
return ProductUpdateResponse(ok=True, message='Товар успешно обновлен')
async def get_by_client_id(self, client_id: int, pagination: PaginationSchema) -> ProductGetResponse:
is_pagination_valid = is_valid_pagination(pagination)
total_pages = 0
total_items = 0
stmt = (
select(Product)
.options(selectinload(Product.barcodes)
@@ -92,7 +96,7 @@ class ProductService(BaseService):
.where(Product.client_id == client_id)
.order_by(Product.id)
)
if is_valid_pagination(pagination):
if is_pagination_valid:
total_products_query = await self.session.execute(
select(
func.cast(func.ceil(func.count() / pagination.items_per_page), Integer),
@@ -101,36 +105,101 @@ class ProductService(BaseService):
.select_from(stmt.subquery())
)
total_pages, total_items = total_products_query.first()
else:
total_items_query = await self.session.execute(
select(func.count())
.select_from(stmt.subquery())
)
total_items = total_items_query.scalar()
total_pages = 1
pagination_info = PaginationInfoSchema(total_pages=total_pages, total_items=total_items)
if is_valid_pagination(pagination):
stmt = (
stmt
.offset(pagination.page * pagination.items_per_page)
.limit(pagination.items_per_page)
)
query = await self.session.execute(
stmt
.order_by(Product.id)
)
product_orm = query.scalars().all()
if not is_pagination_valid:
total_pages = 1
total_items = len(product_orm)
pagination_info = PaginationInfoSchema(total_pages=total_pages, total_items=total_items)
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.from_sql_model(product, {'barcodes': barcodes})
)
for product in product_orm:
products.append(ProductSchema.model_validate(product))
return ProductGetResponse(products=products, pagination_info=pagination_info)
async def get_by_id(self, product_id: int) -> ProductSchema:
stmt = (
select(Product)
.options(selectinload(Product.barcodes)
.noload(ProductBarcode.product))
.where(Product.id == product_id)
)
query = await self.session.execute(stmt)
product = query.scalar()
if not product:
raise HTTPException(status_code=404, detail='Товар не найден')
return ProductSchema.model_validate(product)
# region Barcodes
async def add_barcode(self, request: ProductAddBarcodeRequest):
try:
product = await self.session.get(Product, request.product_id)
if not product:
raise HTTPException(status_code=404, detail='Товар не найден')
existing_barcode_query = await self.session.execute(
select(ProductBarcode)
.where(ProductBarcode.product_id == request.product_id,
ProductBarcode.barcode == request.barcode)
)
existing_barcode = existing_barcode_query.first()
if existing_barcode:
return ProductAddBarcodeResponse(ok=False, message='Штрих-код уже существует у товара')
product_barcode = ProductBarcode(product_id=product.id,
barcode=request.barcode)
self.session.add(product_barcode)
await self.session.commit()
return ProductAddBarcodeResponse(ok=True, message='Штрих-код успешно добавлен')
except Exception as e:
await self.session.rollback()
return ProductAddBarcodeResponse(ok=False, message=str(e))
async def delete_barcode(self, request: ProductDeleteBarcodeRequest):
try:
product_barcode = await self.session.get(ProductBarcode, (request.product_id, request.barcode))
if not product_barcode:
return ProductDeleteBarcodeResponse(ok=False, message='Штрих-код не найден')
await self.session.delete(product_barcode)
await self.session.commit()
return ProductDeleteBarcodeResponse(ok=True, message='Штрих-код успешно удален')
except Exception as e:
await self.session.rollback()
return ProductDeleteBarcodeResponse(ok=False, message=str(e))
async def exists_barcode(self, product_id: int, barcode: str) -> ProductExistsBarcodeResponse:
product_barcode_query = await self.session.execute(
select(ProductBarcode)
.where(ProductBarcode.product_id == product_id,
ProductBarcode.barcode == barcode)
)
product_barcode = product_barcode_query.first()
return ProductExistsBarcodeResponse(exists=bool(product_barcode))
async def generate_barcode(self, request: ProductGenerateBarcodeRequest) -> ProductGenerateBarcodeResponse:
try:
product = await self.session.get(Product, request.product_id)
if not product:
raise HTTPException(status_code=404, detail='Товар не найден')
barcode = utils.barcodes.generate_barcode(product.id)
barcode_exists_query = await self.session.execute(
select(ProductBarcode)
.where(ProductBarcode.barcode == barcode)
)
barcode_exists = barcode_exists_query.first()
if barcode_exists:
raise Exception('Штрих-код уже существует')
product_barcode = ProductBarcode(product_id=product.id,
barcode=barcode)
self.session.add(product_barcode)
await self.session.commit()
return ProductGenerateBarcodeResponse(ok=True, message='Штрих-код успешно сгенерирован', barcode=barcode)
except Exception as e:
return ProductGenerateBarcodeResponse(ok=False, message=str(e))
# endregion