Implement professional PDF-based label printing for boxes and locations

- Replace ZPL/image-based printing with ReportLab PDF generation
- Box labels: 8cm x 5cm landscape with 'BOX Nr:' header and CODE128 barcode
- Location labels: 8cm x 5cm landscape with 'Location nr:' header and CODE128 barcode
- Add /generate_box_label_pdf endpoint using same approach as print_module
- Update FG scan quick box creation to use PDF printing with default printer
- Switch from CDN QZ Tray to local patched version for pairing-key auth
- Improve error handling and logging throughout printing workflow
- Fix import issues (add mm unit to warehouse.py)
- Optimize barcode size and spacing for better readability
This commit is contained in:
Quality App System
2025-12-26 22:28:29 +02:00
parent d4283098a6
commit 9a2e21796e
5 changed files with 375 additions and 63 deletions

View File

@@ -3710,6 +3710,133 @@ def generate_labels_pdf(order_id, paper_saving_mode='true'):
return jsonify({'error': str(e)}), 500
@bp.route('/generate_box_label_pdf', methods=['POST'])
def generate_box_label_pdf():
"""Generate a PDF box label with barcode for printing via QZ Tray"""
if 'role' not in session:
return jsonify({'error': 'Access denied. Please log in.'}), 403
try:
from io import BytesIO
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.graphics.barcode import code128
from flask import make_response
# Get box number from request
box_number = request.form.get('box_number', 'Unknown')
print(f"DEBUG: Generating box label PDF for box: {box_number}")
# Create PDF buffer
pdf_buffer = BytesIO()
# Create canvas with 8cm x 5cm size in landscape orientation
page_width = 80 * mm # 8 cm
page_height = 50 * mm # 5 cm
c = canvas.Canvas(pdf_buffer, pagesize=(page_width, page_height))
# Optimize for label printer
c.setPageCompression(1)
c.setCreator("Trasabilitate Box Label System")
c.setTitle("Box Label - Optimized for Label Printers")
# Define margins and usable area
margin = 2 * mm
usable_width = page_width - (2 * margin)
usable_height = page_height - (2 * margin)
# Calculate vertical layout
# Top section: "BOX Nr: XXXXXXXX" text
# Bottom section: Barcode
text_height = 12 * mm # Space for text at top (reduced from 15mm)
barcode_height = usable_height - text_height - (1 * mm) # Rest for barcode with minimal spacing (reduced from 3mm)
# === TOP SECTION: BOX Nr Label ===
# Position from top of usable area
text_y = page_height - margin - text_height
# Draw "BOX Nr:" label
c.setFont("Helvetica-Bold", 14)
label_text = "BOX Nr:"
label_width = c.stringWidth(label_text, "Helvetica-Bold", 14)
# Draw box number
c.setFont("Helvetica-Bold", 18)
number_text = box_number
number_width = c.stringWidth(number_text, "Helvetica-Bold", 18)
# Calculate total width and center everything
total_text_width = label_width + 3*mm + number_width # 3mm spacing between label and number
start_x = margin + (usable_width - total_text_width) / 2
# Draw label text
c.setFont("Helvetica-Bold", 14)
c.drawString(start_x, text_y + 5*mm, label_text)
# Draw box number
c.setFont("Helvetica-Bold", 18)
c.drawString(start_x + label_width + 3*mm, text_y + 5*mm, number_text)
# === BOTTOM SECTION: Barcode ===
barcode_y = margin
try:
# Create barcode for box number
barcode = code128.Code128(
box_number,
barWidth=0.4*mm, # Thicker bars for better scanning
barHeight=barcode_height,
humanReadable=True,
fontSize=10
)
# Calculate scaling to fit width
scale_factor = usable_width / barcode.width
# Center the barcode horizontally
barcode_x = margin + (usable_width - (barcode.width * scale_factor)) / 2
# Draw the barcode
c.saveState()
c.translate(barcode_x, barcode_y)
c.scale(scale_factor, 1)
barcode.drawOn(c, 0, 0)
c.restoreState()
print(f"DEBUG: Barcode generated successfully with scale factor: {scale_factor}")
except Exception as e:
print(f"DEBUG: Error generating barcode: {e}")
# Fallback: draw text if barcode fails
c.setFont("Helvetica-Bold", 12)
text_width = c.stringWidth(box_number, "Helvetica-Bold", 12)
c.drawString((page_width - text_width) / 2, barcode_y + barcode_height/2, box_number)
c.save()
# Get PDF data
pdf_buffer.seek(0)
pdf_data = pdf_buffer.getvalue()
# Create response
response = make_response(pdf_data)
response.headers['Content-Type'] = 'application/pdf'
response.headers['Content-Disposition'] = f'inline; filename="box_label_{box_number}.pdf"'
print(f"DEBUG: Box label PDF generated successfully")
return response
except Exception as e:
print(f"DEBUG: Error generating box label PDF: {e}")
import traceback
traceback.print_exc()
return jsonify({'error': str(e)}), 500
@bp.route('/generate_label_pdf', methods=['POST'])
def generate_label_pdf():
"""Generate a single label PDF for thermal printing via QZ Tray"""