From 80a74ac8e64acb5c6160952586cfaac881579bde Mon Sep 17 00:00:00 2001 From: AlexSserb Date: Sat, 1 Nov 2025 14:25:22 +0400 Subject: [PATCH] feat: get deal barcodes pdf --- main.py | 2 +- .../repositories/deal_product.py | 1 + modules/fulfillment_base/schemas/product.py | 8 +++ .../services/barcode_printer_service.py | 59 +++++++++++++++++-- .../v1/modules/fulfillment_base/product.py | 21 ++++++- 5 files changed, 82 insertions(+), 9 deletions(-) diff --git a/main.py b/main.py index 12ba079..0f75fef 100644 --- a/main.py +++ b/main.py @@ -13,7 +13,7 @@ def create_app() -> FastAPI: separate_input_output_schemas=True, default_response_class=settings.DEFAULT_RESPONSE_CLASS, root_path=settings.ROOT_PATH, - lifespan=lifespan, + # lifespan=lifespan, ) register_middlewares(app) diff --git a/modules/fulfillment_base/repositories/deal_product.py b/modules/fulfillment_base/repositories/deal_product.py index 44d3769..37a9b7f 100644 --- a/modules/fulfillment_base/repositories/deal_product.py +++ b/modules/fulfillment_base/repositories/deal_product.py @@ -26,6 +26,7 @@ class DealProductRepository( return ( stmt.options( joinedload(DealProduct.product).selectinload(Product.barcodes), + joinedload(DealProduct.product).joinedload(Product.client), selectinload(DealProduct.product_services).joinedload( DealProductService.service ), diff --git a/modules/fulfillment_base/schemas/product.py b/modules/fulfillment_base/schemas/product.py index 7493794..24b8403 100644 --- a/modules/fulfillment_base/schemas/product.py +++ b/modules/fulfillment_base/schemas/product.py @@ -97,6 +97,10 @@ class GetProductBarcodePdfRequest(BaseSchema): barcode: str +class GetDealBarcodesPdfRequest(BaseSchema): + deal_id: int + + # endregion # region Response @@ -127,6 +131,10 @@ class GetProductBarcodePdfResponse(BasePdfResponse): pass +class GetDealBarcodesPdfResponse(BasePdfResponse): + pass + + class BarcodeUploadImageResponse(BaseResponse): image_url: Optional[str] = None diff --git a/modules/fulfillment_base/services/barcode_printer_service.py b/modules/fulfillment_base/services/barcode_printer_service.py index 89ca1b2..27711af 100644 --- a/modules/fulfillment_base/services/barcode_printer_service.py +++ b/modules/fulfillment_base/services/barcode_printer_service.py @@ -5,9 +5,15 @@ from sqlalchemy.ext.asyncio import AsyncSession from modules.fulfillment_base.barcodes_pdf_gen import BarcodePdfGenerator, BarcodeData from modules.fulfillment_base.barcodes_pdf_gen.types import PdfBarcodeImageGenData -from modules.fulfillment_base.models import Product -from modules.fulfillment_base.repositories import ProductRepository -from modules.fulfillment_base.schemas.product import GetProductBarcodePdfRequest +from modules.fulfillment_base.models import Product, DealProduct +from modules.fulfillment_base.repositories import ( + ProductRepository, + DealProductRepository, +) +from modules.fulfillment_base.schemas.product import ( + GetProductBarcodePdfRequest, + GetDealBarcodesPdfRequest, +) class BarcodePrinterService: @@ -16,7 +22,7 @@ class BarcodePrinterService: def __init__(self, session: AsyncSession): self.session = session - async def generate_pdf( + async def generate_product_pdf( self, request: GetProductBarcodePdfRequest ) -> tuple[str, BytesIO]: product: Product = await ProductRepository(self.session).get_by_id( @@ -41,9 +47,50 @@ class BarcodePrinterService: generator = BarcodePdfGenerator(size.width, size.height) return filename, await generator.generate([barcode_data]) - async def generate_base64( + async def generate_product_base64( self, request: GetProductBarcodePdfRequest ) -> tuple[str, str]: - filename, pdf_buffer = await self.generate_pdf(request) + filename, pdf_buffer = await self.generate_product_pdf(request) + base64_string = base64.b64encode(pdf_buffer.read()).decode("utf-8") + return filename, base64_string + + async def generate_deal_pdf( + self, request: GetDealBarcodesPdfRequest + ) -> tuple[str, BytesIO]: + deal_product_repo = DealProductRepository(self.session) + deal_products: list[DealProduct] = await deal_product_repo.get_all( + request.deal_id + ) + + if len(deal_products) == 0: + return "no_content.pdf", BytesIO() + + barcodes_data: list[BarcodeData | PdfBarcodeImageGenData] = [] + + for deal_product in deal_products: + if deal_product.product.barcode_image: + barcode_data: PdfBarcodeImageGenData = { + "barcode_image_url": deal_product.product.barcode_image.image_url, + "num_duplicates": deal_product.quantity, + } + barcodes_data.append(barcode_data) + elif len(deal_product.product.barcodes) > 0: + barcode_data: BarcodeData = { + "barcode": deal_product.product.barcodes[0].barcode, + "template": deal_product.product.barcode_template, + "product": deal_product.product, + "num_duplicates": deal_product.quantity, + } + barcodes_data.append(barcode_data) + + size = deal_products[0].product.barcode_template.size + generator = BarcodePdfGenerator(size.width, size.height) + filename = "deal_barcodes.pdf" + return filename, await generator.generate(barcodes_data) + + async def generate_deal_base64( + self, request: GetDealBarcodesPdfRequest + ) -> tuple[str, str]: + filename, pdf_buffer = await self.generate_deal_pdf(request) base64_string = base64.b64encode(pdf_buffer.read()).decode("utf-8") return filename, base64_string diff --git a/routers/crm/v1/modules/fulfillment_base/product.py b/routers/crm/v1/modules/fulfillment_base/product.py index 7821a68..3b54da8 100644 --- a/routers/crm/v1/modules/fulfillment_base/product.py +++ b/routers/crm/v1/modules/fulfillment_base/product.py @@ -79,10 +79,27 @@ async def delete_product( response_model=GetProductBarcodePdfResponse, ) async def get_product_barcode_pdf( - request: GetProductBarcodePdfRequest, session: SessionDependency + session: SessionDependency, + request: GetProductBarcodePdfRequest, ): service = BarcodePrinterService(session) - filename, base64_string = await service.generate_base64(request) + filename, base64_string = await service.generate_product_base64(request) + return GetProductBarcodePdfResponse( + base64_string=base64_string, filename=filename, mime_type="application/pdf" + ) + + +@router.post( + "/barcode/for-deal/get-pdf", + operation_id="get_deal_barcodes_pdf", + response_model=GetDealBarcodesPdfResponse, +) +async def get_deal_barcodes_pdf( + session: SessionDependency, + request: GetDealBarcodesPdfRequest, +): + service = BarcodePrinterService(session) + filename, base64_string = await service.generate_deal_base64(request) return GetProductBarcodePdfResponse( base64_string=base64_string, filename=filename, mime_type="application/pdf" )