import base64 import os import textwrap from io import BytesIO from time import time import fitz from PyPDF2 import PdfReader, PdfWriter from fastapi import APIRouter, UploadFile, File from reportlab.graphics.barcode import code128 from reportlab.lib.units import mm from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfgen import canvas from starlette.exceptions import HTTPException from starlette.requests import Request from app import mongo from app.utils.response_util import response router = APIRouter() STATIC_FOLDER = "static" BARCODES_FOLDER = os.path.join(STATIC_FOLDER, "barcodes") os.makedirs(BARCODES_FOLDER, exist_ok=True) @router.post("/get", tags=[""]) async def get_barcode(params: dict): start_time = time() return response({ "barcode": params["barcode"] }, start_time=start_time) @router.post("/add", tags=[""]) async def add_barcode(params: dict): start_time = time() product = await mongo.products_collection.find_one({ "id": params["productId"] }, { "_id": False }) barcodes = product["barcodes"] barcodes.append(params["barcode"]) await mongo.products_collection.update_one({ "id": params["productId"] }, { "$set": {"barcodes": barcodes} }) return response({ "message": "Штрихкод добавлен", "ok": True }, start_time=start_time) @router.get("/exists", tags=[""]) async def barcode_exists(product_id: int, barcode: str): start_time = time() product = await mongo.products_collection.find_one({ "id": product_id }, { "_id": False }) return response({ "exists": barcode in product["barcodes"] }, start_time=start_time) @router.post("/get-pdf", tags=[""]) async def get_barcode_pdf(params: dict): product_id = params["productId"] quantity = params['quantity'] pdf_path = os.path.join(BARCODES_FOLDER, f"{product_id}.pdf") if os.path.exists(pdf_path): with open(pdf_path, "rb") as file: existing_pdf = PdfReader(file) buffer = BytesIO() new_pdf = PdfWriter() for _ in range(quantity): for page_num in range(len(existing_pdf.pages)): page = existing_pdf.pages[page_num] new_pdf.add_page(page) new_pdf.write(buffer) buffer.seek(0) return { "base64String": base64.b64encode(buffer.getvalue()).decode("utf-8"), "mimeType": "application/pdf" } product = await mongo.products_collection.find_one( {"id": product_id}, {"_id": False} ) client = await mongo.clients_collection.find_one( {"id": product["clientId"]}, {"_id": False} ) barcode_template = await mongo.templates_collection.find_one( {"id": product["barcodeTemplate"]["id"]} if product["barcodeTemplate"] else {}, {"_id": False} ) attributes = { attribute["key"]: attribute["name"] for attribute in barcode_template["attributes"] } buffer = BytesIO() pdf = canvas.Canvas(buffer, pagesize=( barcode_template["size"]["width"] * mm, barcode_template["size"]["height"] * mm )) pdf.setTitle("Product Barcode Information") pdfmetrics.registerFont(TTFont('Arial', 'assets/arial.ttf')) pdfmetrics.registerFont(TTFont('Arial Bold', 'assets/arial_bold.ttf')) for _ in range(quantity): name_lines = textwrap.wrap(product["name"], width=24) text_y = 36 * mm pdf.setFont("Arial Bold", 9) for line in name_lines: pdf.drawCentredString(29 * mm, text_y, line) text_y -= 3 * mm pdf.setFont("Arial", 7) if "article" in attributes: pdf.drawString(6 * mm, text_y, f"{attributes['article']}: {product['article']}") text_y -= 3 * mm if "brand" in attributes and product.get("brand"): pdf.drawString(6 * mm, text_y, f"{attributes['brand']}: {product['brand']}") text_y -= 3 * mm if "client.name" in attributes and client: pdf.drawString(6 * mm, text_y, client["name"]) text_y -= 3 * mm if "color" in attributes and product.get("color"): pdf.drawString(6 * mm, text_y, f"{attributes['color']}: {product['color']}") text_y -= 3 * mm if "size" in attributes and product.get("size"): pdf.drawString(6 * mm, text_y, f"{attributes['size']}: {product['size']}") text_y -= 3 * mm barcode = code128.Code128(params["barcode"], barWidth=0.3 * mm, barHeight=10 * mm) barcode.drawOn(pdf, 5 * mm, text_y - 8 * mm) pdf.drawCentredString(29 * mm, text_y - 11 * mm, params["barcode"]) pdf.showPage() pdf.save() buffer.seek(0) return { "base64String": base64.b64encode(buffer.getvalue()).decode("utf-8"), "mimeType": "application/pdf" } @router.post("/upload-image/{product_id}", tags=[""]) async def upload_product_barcode_image( request: Request, product_id: int, upload_file: UploadFile = File(...) ): start_time = time() product = await mongo.products_collection.find_one({"id": product_id}) if not product: raise HTTPException(status_code=404, detail="Product not found") extension = os.path.splitext(upload_file.filename)[1] or ".pdf" filename = f"{product_id}{extension}" file_path = os.path.join(BARCODES_FOLDER, filename) with open(file_path, "wb") as file: file.write(await upload_file.read()) document = fitz.open(file_path) page = document.load_page(0) pixmap = page.get_pixmap() output_image_filename = f"{product_id}.png" output_image_path = os.path.join(BARCODES_FOLDER, output_image_filename) pixmap.save(output_image_path) document.close() barcode_image_url = f"{str(request.base_url).rstrip('/')}/api/files/barcodes/{output_image_filename}" return response({ "barcodeImageUrl": barcode_image_url, "message": "Штрихкод успешно загружен!", "ok": True }, start_time=start_time) @router.post("/delete-image/{product_id}", tags=[""]) async def delete_product_barcode_image(product_id: int): start_time = time() pdf_path = os.path.join(BARCODES_FOLDER, f"{product_id}.pdf") png_path = os.path.join(BARCODES_FOLDER, f"{product_id}.png") if not os.path.exists(pdf_path): raise HTTPException(status_code=404, detail="Barcode PDF not found") if os.path.exists(pdf_path): os.remove(pdf_path) if os.path.exists(png_path): os.remove(png_path) return response({ "message": "Штрихкод успешно удалён!", "ok": True }, start_time=start_time) @router.post("/image/{product_id}", tags=[""]) async def get_product_barcode_image(request: Request, product_id: int): start_time = time() image_filename = f"{product_id}.png" image_path = os.path.join(BARCODES_FOLDER, image_filename) if not os.path.exists(image_path): raise HTTPException(status_code=404, detail="Barcode image not found") barcode_image_url = f"{str(request.base_url).rstrip('/')}/api/files/barcodes/{image_filename}" return response({ "barcodeImageUrl": barcode_image_url, "ok": True, "message": "Штрихкод найден!" }, start_time=start_time)