mirror of
https://github.com/Horizontal42/warehouse-master.git
synced 2026-11-10 16:02:07 +03:00
PyQt5 desktop app: PDF label generator (single/2×2/4×4 grids) and Google Sheets reassembly tracker for laptop inventory management.
107 lines
3.9 KiB
Python
107 lines
3.9 KiB
Python
from __future__ import annotations
|
|
|
|
from PyQt5.QtCore import QThread, pyqtSignal
|
|
from reportlab.lib.pagesizes import landscape
|
|
from reportlab.lib.units import mm
|
|
from reportlab.pdfgen import canvas
|
|
|
|
PAGE_SIZES: dict[str, tuple[float, float]] = {
|
|
"single": (58 * mm, 40 * mm),
|
|
"grid_2x2": (58 * mm, 40 * mm),
|
|
"grid_4x4": (120 * mm, 75 * mm),
|
|
}
|
|
DEFAULT_FONT_SIZES: dict[str, int] = {"single": 32, "grid_2x2": 24, "grid_4x4": 36}
|
|
|
|
|
|
class PDFWorker(QThread):
|
|
finished = pyqtSignal(str)
|
|
error_occurred = pyqtSignal(str)
|
|
|
|
def __init__(self, ranges, label_type, label_name, font_size, font_name, filepath):
|
|
super().__init__()
|
|
self.ranges = ranges
|
|
self.label_type = label_type
|
|
self.label_name = label_name
|
|
self.font_size = font_size
|
|
self.font_name = font_name
|
|
self.filepath = filepath
|
|
|
|
def run(self):
|
|
try:
|
|
if not self.ranges:
|
|
raise ValueError("No ranges defined")
|
|
pw, ph = PAGE_SIZES[self.label_type]
|
|
if self.label_type == "single":
|
|
page_size = landscape((pw, ph))
|
|
cols, rows = 1, 1
|
|
elif self.label_type == "grid_2x2":
|
|
page_size = (pw, ph)
|
|
cols, rows = 2, 2
|
|
else:
|
|
page_size = (pw, ph)
|
|
cols, rows = 4, 4
|
|
c = canvas.Canvas(self.filepath, pagesize=page_size)
|
|
c.setFont(self.font_name, self.font_size)
|
|
cell_w = pw / cols
|
|
cell_h = ph / rows
|
|
items_per_page = cols * rows
|
|
idx = 0
|
|
for start, end in self.ranges:
|
|
for num in range(start, end + 1):
|
|
col = idx % cols
|
|
row = idx // cols
|
|
if self.label_type == "single":
|
|
c.drawCentredString(pw / 2, ph / 2 + 5 * mm, self.label_name)
|
|
c.drawCentredString(pw / 2, ph / 2 - 5 * mm, f"№ {num}")
|
|
else:
|
|
x = col * cell_w + cell_w / 2
|
|
y = ph - (row + 1) * cell_h + cell_h / 2 - self.font_size / 3
|
|
c.drawCentredString(x, y, str(num))
|
|
idx += 1
|
|
if idx >= items_per_page:
|
|
c.showPage()
|
|
c.setFont(self.font_name, self.font_size)
|
|
idx = 0
|
|
if idx > 0:
|
|
c.showPage()
|
|
c.save()
|
|
self.finished.emit(self.filepath)
|
|
except Exception as e:
|
|
self.error_occurred.emit(str(e))
|
|
|
|
|
|
class ReassemblyWorker(QThread):
|
|
finished_signal = pyqtSignal(str, str)
|
|
error_signal = pyqtSignal(str)
|
|
|
|
def __init__(self, sheet_url, cfg_path, order_prefix, order_num, laptop_id, parts_str, ssd_id, akb_id):
|
|
super().__init__()
|
|
self.sheet_url = sheet_url
|
|
self.cfg_path = cfg_path
|
|
self.order_prefix = order_prefix
|
|
self.order_num = order_num
|
|
self.laptop_id = laptop_id
|
|
self.parts_str = parts_str
|
|
self.ssd_id = ssd_id
|
|
self.akb_id = akb_id
|
|
|
|
def run(self):
|
|
try:
|
|
try:
|
|
from sheet_manager import SheetManager
|
|
except ImportError as e:
|
|
self.error_signal.emit(f"Google Sheets dependencies not installed: {e}")
|
|
return
|
|
manager = SheetManager(self.sheet_url, self.cfg_path)
|
|
serial, report_lines, tech_lines = manager.process_reassembly(
|
|
self.laptop_id, self.parts_str, self.ssd_id, self.akb_id
|
|
)
|
|
comment = (
|
|
f"{self.order_prefix} {self.order_num}\n"
|
|
f"{self.laptop_id} {serial}\n"
|
|
+ "\n".join(report_lines)
|
|
)
|
|
tech_op = f"Parts for {self.laptop_id} (S/N {serial}):\n" + "\n".join(tech_lines)
|
|
self.finished_signal.emit(comment, tech_op)
|
|
except Exception as e:
|
|
self.error_signal.emit(str(e))
|