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:
@@ -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"""
|
||||
|
||||
Reference in New Issue
Block a user