first commit

This commit is contained in:
2025-07-24 20:13:47 +03:00
commit 94b7585f8b
175 changed files with 85264 additions and 0 deletions

View File

@ -0,0 +1,9 @@
from fastapi import APIRouter
from app.api.v1.product import product, barcode, images
router = APIRouter()
router.include_router(product.router)
router.include_router(barcode.router, prefix='/barcode')
router.include_router(images.router, prefix='/images')

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,246 @@
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)

View File

@ -0,0 +1,40 @@
import os
from time import time
from fastapi import APIRouter, UploadFile, File, HTTPException, Request
from app import mongo
from app.utils.response_util import response
router = APIRouter()
STATIC_FOLDER = "static"
PRODUCTS_FOLDER = os.path.join(STATIC_FOLDER, "images")
os.makedirs(PRODUCTS_FOLDER, exist_ok=True)
@router.post("/upload/{product_id}", tags=["Products"])
async def upload_product_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 ".jpg"
filename = f"{product_id}{extension}"
file_path = os.path.join(PRODUCTS_FOLDER, filename)
with open(file_path, "wb") as file:
file.write(await upload_file.read())
image_url = f"{str(request.base_url).rstrip('/')}/api/files/images/{filename}"
return response({
"imageUrl": image_url,
"message": "Фото успешно загружено!",
"ok": True
}, start_time=start_time)

View File

@ -0,0 +1,129 @@
from time import time
from fastapi import APIRouter
from app import mongo
from app.utils.response_util import response
router = APIRouter()
@router.get("/get-by-id", tags=[""])
async def get_by_id(product_id: int = None):
start_time = time()
product = await mongo.products_collection.find_one({
"id": product_id
}, {
"_id": False
})
return response(product, start_time=start_time)
@router.get("/get", tags=[""])
async def get(client_id: int = None, search_input: str = None, page: int = 0, items_per_page: int = 10):
start_time = time()
filter = dict()
if client_id:
filter["clientId"] = client_id
if search_input:
filter["$or"] = [
{
"name": {
"$regex": search_input
}
},
{
"article": {
"$regex": search_input
}
},
{
"factoryArticle": {
"$regex": search_input
}
},
{
"barcodes": {
"$regex": search_input
}
}
]
products = await mongo.products_collection.find(filter, {
"_id": False
}).limit(items_per_page).skip(items_per_page * page).to_list()
products_count = await mongo.products_collection.count_documents(filter)
return response({
"paginationInfo": {
"totalItems": products_count,
"totalPages": round(products_count / items_per_page)
},
"products": products
}, start_time=start_time)
@router.post("/create", tags=[""])
async def create(data: dict):
start_time = time()
data["id"] = await mongo.get_next_id(mongo.products_collection)
try:
await mongo.products_collection.insert_one(data)
return response({
"message": "Продукт создан",
"ok": True
}, start_time=start_time)
except Exception as e:
return response({
"message": str(e),
"ok": False
}, start_time=start_time, code=400)
@router.post("/update", tags=[""])
async def update(params: dict):
start_time = time()
data = params["product"]
try:
await mongo.products_collection.update_one({
"id": data["id"]
}, {
"$set": data
})
return response({
"message": "Данные продукта обновлены",
"ok": True
}, start_time=start_time)
except Exception as e:
return response({
"message": str(e),
"ok": False
}, start_time=start_time, code=400)
@router.post("/delete", tags=[""])
async def delete(params: dict):
start_time = time()
product_id = params["productId"]
try:
await mongo.products_collection.delete_one({
"id": product_id
})
return response({
"message": "Продукт удален",
"ok": True
}, start_time=start_time)
except Exception as e:
return response({
"message": str(e),
"ok": False
}, start_time=start_time, code=400)