From 6029a2b98e96b5c72b70c619ba88e8080db656e8 Mon Sep 17 00:00:00 2001 From: Quality App Developer Date: Sun, 15 Feb 2026 17:57:45 +0200 Subject: [PATCH] Fix barcode format and improve scannability - Changed sequential numbering from slash to hyphen format (TEST-ORD-004-0001) - Increased horizontal barcode bar width from 0.25mm to 0.30mm for better scanning - Increased vertical barcode bar width from 0.15mm to 0.30mm for reliable readability - Changed from 3-digit to 4-digit padding for piece numbers (0001 instead of 001) - Removed aggressive scaling that was distorting barcode bars - Barcodes now use optimal settings for thermal printers and handheld scanners --- app/db_schema_verifier.py | 2 +- app/modules/labels/pdf_generator.py | 47 +++++++++++-------- .../modules/labels/print_labels.html | 33 +++++++------ .../modules/labels/print_lost_labels.html | 10 ++-- .../modules/labels/print_lost_labels_new.html | 10 ++-- initialize_db.py | 2 +- 6 files changed, 58 insertions(+), 46 deletions(-) diff --git a/app/db_schema_verifier.py b/app/db_schema_verifier.py index 5ccbb0b..53c3a73 100755 --- a/app/db_schema_verifier.py +++ b/app/db_schema_verifier.py @@ -389,7 +389,7 @@ class SchemaVerifier: open_for_order TINYINT(1) DEFAULT 1, line_number INT, printed_labels TINYINT(1) DEFAULT 0, - data_livrara DATE, + data_livrare DATE, dimensiune VARCHAR(50), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, diff --git a/app/modules/labels/pdf_generator.py b/app/modules/labels/pdf_generator.py index fd769dc..8e79b57 100755 --- a/app/modules/labels/pdf_generator.py +++ b/app/modules/labels/pdf_generator.py @@ -87,8 +87,8 @@ class LabelPDFGenerator: if printer_optimized: self._optimize_for_label_printer(c) - # Create sequential label number: CP00000711/001, CP00000711/002, etc. - sequential_number = f"{prod_order}/{i:03d}" + # Create sequential label number: CP00000711-0001, CP00000711-0002, etc. + sequential_number = f"{prod_order}-{i:04d}" # Draw single label self._draw_label(c, order_data, sequential_number, i, quantity) @@ -116,7 +116,7 @@ class LabelPDFGenerator: prod_order = order_data.get('comanda_productie', 'CP00000000') # Create sequential label number with specific piece number - sequential_number = f"{prod_order}/{piece_number:03d}" + sequential_number = f"{prod_order}-{piece_number:04d}" print(f"DEBUG: Generating label {sequential_number} (piece {piece_number} of {total_pieces})") @@ -301,7 +301,7 @@ class LabelPDFGenerator: canvas.setFont("Helvetica-Bold", 10) # Match HTML: comanda_productie + "-" + sequential number (not quantity!) comanda_productie = str(order_data.get('comanda_productie', 'N/A')) - prod_order = f"{comanda_productie}-{current_num:03d}" # Sequential number for this specific label + prod_order = f"{comanda_productie}-{current_num:04d}" # Sequential number for this specific label po_text_width = canvas.stringWidth(prod_order, "Helvetica-Bold", 10) po_x_centered = vertical_x + (self.right_column_width - po_text_width) / 2 canvas.drawString(po_x_centered, row_y + self.row_height/3, prod_order) @@ -321,17 +321,23 @@ class LabelPDFGenerator: try: # Create barcode for sequential number + # OPTIMIZED FOR SCANNING: 0.30mm bar width for reliable readability barcode = code128.Code128(sequential_number, - barWidth=0.25*mm, # Adjust bar width for better fit - barHeight=mm_to_points(10)) # Increase height to 10mm + barWidth=0.30*mm, # Increased from 0.25mm for better scanning + barHeight=mm_to_points(10)) # 10mm height - # Always scale to fit the full allocated width - scale_factor = barcode_width / barcode.width - canvas.saveState() - canvas.translate(barcode_x, barcode_y) - canvas.scale(scale_factor, 1) - barcode.drawOn(canvas, 0, 0) - canvas.restoreState() + # Only scale if barcode is too wide, otherwise use natural size + if barcode.width > barcode_width: + scale_factor = barcode_width / barcode.width + canvas.saveState() + canvas.translate(barcode_x, barcode_y) + canvas.scale(scale_factor, 1) + barcode.drawOn(canvas, 0, 0) + canvas.restoreState() + else: + # Use natural size - center it in available space + x_offset = (barcode_width - barcode.width) / 2 + barcode.drawOn(canvas, barcode_x + x_offset, barcode_y) # NO TEXT BELOW BARCODE - Remove all text rendering for horizontal barcode @@ -362,18 +368,21 @@ class LabelPDFGenerator: vertical_code = "000000/00" # Create a vertical barcode using Code128 + # OPTIMIZED FOR SCANNING: 0.30mm bar width for reliable readability v_barcode = code128.Code128(vertical_code, - barWidth=0.15*mm, # Thinner bars for better fit - barHeight=mm_to_points(8)) # Increased bar height + barWidth=0.30*mm, # Increased from 0.15mm for better scanning + barHeight=mm_to_points(10)) # Increased bar height - # Draw rotated barcode - fill the entire frame height + # Draw rotated barcode - fit naturally without aggressive scaling canvas.saveState() canvas.translate(vertical_barcode_x + mm_to_points(6), vertical_barcode_y) canvas.rotate(90) - # Always scale to fill the frame height - scale_factor = vertical_barcode_height / v_barcode.width - canvas.scale(scale_factor, 1) + # Only scale if barcode is too wide for frame, otherwise use natural size + if v_barcode.width > vertical_barcode_height: + scale_factor = vertical_barcode_height / v_barcode.width + canvas.scale(scale_factor, 1) + # else: use natural size for best scanning quality v_barcode.drawOn(canvas, 0, 0) canvas.restoreState() diff --git a/app/templates/modules/labels/print_labels.html b/app/templates/modules/labels/print_labels.html index dcf538e..613c764 100755 --- a/app/templates/modules/labels/print_labels.html +++ b/app/templates/modules/labels/print_labels.html @@ -495,9 +495,9 @@ function updateLabelPreview(order) { const prodOrder = comandaProductie && cantitate ? `${comandaProductie}-${cantitate}` : 'N/A'; document.getElementById('prod-order-value').textContent = prodOrder; - // Update horizontal barcode with CP format (e.g., CP00000711/001) - // Show the first piece number (001) in preview - const horizontalBarcodeData = comandaProductie ? `${comandaProductie}/001` : 'SAMPLE001'; + // Update horizontal barcode with correct format (e.g., TEST-ORD-006-0001) + // Show the first piece number (0001) in preview + const horizontalBarcodeData = comandaProductie ? `${comandaProductie}-${String(1).padStart(4, '0')}` : 'SAMPLE-0001'; document.getElementById('barcode-text').textContent = horizontalBarcodeData; // Generate horizontal barcode visual using JsBarcode @@ -533,8 +533,9 @@ function updateLabelPreview(order) { horizontalBarcodeData === 'N/A' ? 'No data' : 'JsBarcode not loaded'); } - // Update vertical barcode with client order format (e.g., Abcderd65) - const verticalBarcodeData = comAchizClient && nrLinie ? `${comAchizClient}${nrLinie}` : 'SAMPLE00'; + // Update vertical barcode with client order format (e.g., CLIENT001/65) + // Must match PDF generator format: com_achiz_client/nr_linie_com_client + const verticalBarcodeData = comAchizClient && nrLinie ? `${comAchizClient}/${nrLinie}` : '000000/00'; document.getElementById('vertical-barcode-text').textContent = verticalBarcodeData; // Generate vertical barcode visual using JsBarcode (will be rotated by CSS) @@ -580,8 +581,8 @@ function clearLabelPreview() { document.getElementById('description-value').textContent = 'N/A'; document.getElementById('article-code-value').textContent = 'N/A'; document.getElementById('prod-order-value').textContent = 'N/A'; - document.getElementById('barcode-text').textContent = 'SAMPLE001'; - document.getElementById('vertical-barcode-text').textContent = 'SAMPLE00'; + document.getElementById('barcode-text').textContent = 'SAMPLE-0001'; + document.getElementById('vertical-barcode-text').textContent = '000000/00'; // Generate sample barcodes instead of clearing generateSampleBarcodes(); @@ -605,8 +606,8 @@ function generateSampleBarcodes() { horizontalElement.innerHTML = ''; console.log('🔍 Horizontal element cleared, generating barcode...'); - // Generate horizontal sample barcode with simpler parameters first - JsBarcode(horizontalElement, "SAMPLE001", { + // Generate horizontal sample barcode with correct format (dash and 4-digit padding) + JsBarcode(horizontalElement, "SAMPLE-0001", { format: "CODE128", width: 1, height: 40, @@ -623,8 +624,8 @@ function generateSampleBarcodes() { verticalElement.innerHTML = ''; console.log('🔍 Vertical element cleared, generating barcode...'); - // Generate vertical sample barcode - JsBarcode(verticalElement, "SAMPLE00", { + // Generate vertical sample barcode with correct format (slash separator) + JsBarcode(verticalElement, "000000/00", { format: "CODE128", width: 1, height: 35, @@ -1084,8 +1085,9 @@ function updatePreview(orderData, pieceNumber, totalPieces) { const deliveryDate = data_livrare ? new Date(data_livrare).toLocaleDateString() : 'N/A'; const clientOrder = com_achiz_client && nr_linie_com_client ? `${com_achiz_client}-${nr_linie_com_client}` : 'N/A'; - const horizontalBarcode = comanda_productie ? `${comanda_productie}-${String(pieceNumber).padStart(3, '0')}` : 'N/A'; - const verticalBarcode = clientOrder; + const horizontalBarcode = comanda_productie ? `${comanda_productie}-${String(pieceNumber).padStart(4, '0')}` : 'N/A'; + // Vertical barcode uses slash separator to match PDF generator + const verticalBarcode = com_achiz_client && nr_linie_com_client ? `${com_achiz_client}/${nr_linie_com_client}` : '000000/00'; const prodOrder = comanda_productie && cantitate ? `${comanda_productie}-${cantitate}` : 'N/A'; // Update preview elements with correct IDs @@ -1135,8 +1137,9 @@ function generateHTMLLabel(orderData, pieceNumber, totalPieces) { // Format data for label (matching preview format) const deliveryDate = data_livrare ? new Date(data_livrare).toLocaleDateString() : 'N/A'; const clientOrder = com_achiz_client && nr_linie_com_client ? `${com_achiz_client}-${nr_linie_com_client}` : 'N/A'; - const horizontalBarcode = comanda_productie ? `${comanda_productie}-${String(pieceNumber).padStart(3, '0')}` : 'N/A'; - const verticalBarcode = clientOrder; + const horizontalBarcode = comanda_productie ? `${comanda_productie}-${String(pieceNumber).padStart(4, '0')}` : 'N/A'; + // Vertical barcode uses slash separator to match PDF generator + const verticalBarcode = com_achiz_client && nr_linie_com_client ? `${com_achiz_client}/${nr_linie_com_client}` : '000000/00'; const prodOrder = comanda_productie && cantitate ? `${comanda_productie}-${cantitate}` : 'N/A'; const htmlContent = ` diff --git a/app/templates/modules/labels/print_lost_labels.html b/app/templates/modules/labels/print_lost_labels.html index 4038d01..0bb0f39 100755 --- a/app/templates/modules/labels/print_lost_labels.html +++ b/app/templates/modules/labels/print_lost_labels.html @@ -559,7 +559,7 @@ async function handleQZTrayPrint(selectedRow) { labelNumbers.push(i); } } else { - alert(`Invalid range. Please use format "001-${String(orderData.cantitate).padStart(3, '0')}" or single number.`); + alert(`Invalid range. Please use format "0001-${String(orderData.cantitate).padStart(4, '0')}" or single number.`); return; } } else { @@ -592,8 +592,8 @@ async function handleQZTrayPrint(selectedRow) { // Show success message const rangeText = labelsRangeInput ? - (labelNumbers.length === 1 ? `label ${String(labelNumbers[0]).padStart(3, '0')}` : - `labels ${String(labelNumbers[0]).padStart(3, '0')}-${String(labelNumbers[labelNumbers.length-1]).padStart(3, '0')}`) : + (labelNumbers.length === 1 ? `label ${String(labelNumbers[0]).padStart(4, '0')}` : + `labels ${String(labelNumbers[0]).padStart(4, '0')}-${String(labelNumbers[labelNumbers.length-1]).padStart(4, '0')}`) : `all ${orderData.cantitate} labels`; alert(`Successfully printed ${rangeText} for order ${orderData.comanda_productie}`); @@ -736,10 +736,10 @@ function updatePreviewCard(order) { set('size-value', order.dimensiune || ''); set('article-code-value', order.cod_articol || ''); set('prod-order-value', (order.comanda_productie && order.cantitate) ? `${order.comanda_productie}-${order.cantitate}` : ''); - set('barcode-text', order.comanda_productie ? `${order.comanda_productie}/001` : ''); + set('barcode-text', order.comanda_productie ? `${order.comanda_productie}-0001` : ''); set('vertical-barcode-text', (order.com_achiz_client && order.nr_linie_com_client) ? `${order.com_achiz_client}/${order.nr_linie_com_client}` : ''); // Generate barcodes if JsBarcode is available (with debugging like print_module.html) - const horizontalBarcodeData = order.comanda_productie ? `${order.comanda_productie}/001` : 'N/A'; + const horizontalBarcodeData = order.comanda_productie ? `${order.comanda_productie}-0001` : 'N/A'; const verticalBarcodeData = (order.com_achiz_client && order.nr_linie_com_client) ? `${order.com_achiz_client}/${order.nr_linie_com_client}` : '000000/00'; console.log('🔍 BARCODE DEBUG - Order data:', order); diff --git a/app/templates/modules/labels/print_lost_labels_new.html b/app/templates/modules/labels/print_lost_labels_new.html index 9ef846f..e1e1d08 100755 --- a/app/templates/modules/labels/print_lost_labels_new.html +++ b/app/templates/modules/labels/print_lost_labels_new.html @@ -542,7 +542,7 @@ async function handleQZTrayPrint(selectedRow) { labelNumbers.push(i); } } else { - alert(`Invalid range. Please use format "001-${String(orderData.cantitate).padStart(3, '0')}" or single number.`); + alert(`Invalid range. Please use format "0001-${String(orderData.cantitate).padStart(4, '0')}" or single number.`); return; } } else { @@ -575,8 +575,8 @@ async function handleQZTrayPrint(selectedRow) { // Show success message const rangeText = labelsRangeInput ? - (labelNumbers.length === 1 ? `label ${String(labelNumbers[0]).padStart(3, '0')}` : - `labels ${String(labelNumbers[0]).padStart(3, '0')}-${String(labelNumbers[labelNumbers.length-1]).padStart(3, '0')}`) : + (labelNumbers.length === 1 ? `label ${String(labelNumbers[0]).padStart(4, '0')}` : + `labels ${String(labelNumbers[0]).padStart(4, '0')}-${String(labelNumbers[labelNumbers.length-1]).padStart(4, '0')}`) : `all ${orderData.cantitate} labels`; alert(`Successfully printed ${rangeText} for order ${orderData.comanda_productie}`); @@ -719,10 +719,10 @@ function updatePreviewCard(order) { set('size-value', order.dimensiune || ''); set('article-code-value', order.cod_articol || ''); set('prod-order-value', (order.comanda_productie && order.cantitate) ? `${order.comanda_productie}-${order.cantitate}` : ''); - set('barcode-text', order.comanda_productie ? `${order.comanda_productie}/001` : ''); + set('barcode-text', order.comanda_productie ? `${order.comanda_productie}-0001` : ''); set('vertical-barcode-text', (order.com_achiz_client && order.nr_linie_com_client) ? `${order.com_achiz_client}/${order.nr_linie_com_client}` : ''); // Generate barcodes if JsBarcode is available (with debugging like print_module.html) - const horizontalBarcodeData = order.comanda_productie ? `${order.comanda_productie}/001` : 'N/A'; + const horizontalBarcodeData = order.comanda_productie ? `${order.comanda_productie}-0001` : 'N/A'; const verticalBarcodeData = (order.com_achiz_client && order.nr_linie_com_client) ? `${order.com_achiz_client}/${order.nr_linie_com_client}` : '000000/00'; console.log('🔍 BARCODE DEBUG - Order data:', order); diff --git a/initialize_db.py b/initialize_db.py index b3d38b5..88260e3 100644 --- a/initialize_db.py +++ b/initialize_db.py @@ -414,7 +414,7 @@ def create_tables(): open_for_order TINYINT(1) DEFAULT 1, line_number INT, printed_labels TINYINT(1) DEFAULT 0, - data_livrara DATE, + data_livrare DATE, dimensiune VARCHAR(50), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,