updated : solutions

This commit is contained in:
2025-09-26 22:51:16 +03:00
parent 1f90602550
commit 5765798905
53 changed files with 256 additions and 7746 deletions

View File

@@ -2065,6 +2065,47 @@ def update_printed_status(order_id):
print(f"DEBUG: Error in update_printed_status: {e}")
return jsonify({'error': 'Internal server error'}), 500
@bp.route('/download_print_service')
def download_print_service():
"""Download the direct print service package"""
try:
from flask import send_from_directory, current_app
import os
# Check if complete package is requested
package_type = request.args.get('package', 'basic')
if package_type == 'complete':
# Serve the complete package
filename = 'QualityPrintService_Complete.zip'
else:
# Serve the basic package (legacy)
filename = 'RecticelPrintService.zip'
# Path to the print service files
service_path = os.path.join(current_app.root_path, 'static', 'downloads')
# Create the directory if it doesn't exist
os.makedirs(service_path, exist_ok=True)
# Check if the zip file exists
full_path = os.path.join(service_path, filename)
if not os.path.exists(full_path):
# If the zip doesn't exist, return information about creating it
return jsonify({
'error': f'Print service package ({filename}) not found',
'message': f'The {package_type} print service package is not available',
'suggestion': 'Please contact the administrator or use the basic package'
}), 404
return send_from_directory(service_path, filename, as_attachment=True)
except Exception as e:
print(f"DEBUG: Error downloading print service: {e}")
return jsonify({'error': 'Failed to download print service'}), 500
@bp.route('/get_order_data/<int:order_id>', methods=['GET'])
def get_order_data(order_id):
"""Get specific order data for preview"""

View File

@@ -204,6 +204,25 @@
<div style="margin-bottom: 5px;">Creates sequential labels based on quantity</div>
<small>(e.g., CP00000711-001 to CP00000711-063)</small>
</div>
<!-- Direct Print Service Download -->
<div style="width: 100%; text-align: center; margin-top: 20px; padding-top: 15px; border-top: 1px solid #e9ecef;">
<div style="background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; padding: 12px; margin-bottom: 10px;">
<div style="font-size: 11px; color: #856404; margin-bottom: 8px;">
<strong>📦 Quality Print Service</strong>
</div>
<div style="font-size: 10px; color: #6c757d; margin-bottom: 10px; line-height: 1.3;">
Professional Windows service for instant direct printing to thermal label printers without PDF dialogs
</div>
<a href="{{ url_for('main.download_print_service') }}?package=complete" class="btn btn-outline-warning btn-sm" download style="font-size: 10px; padding: 4px 12px; text-decoration: none;">
📥 Download Complete Package
</a>
</div>
<div style="font-size: 9px; color: #6c757d; margin-top: 5px; line-height: 1.2;">
<strong>Easy Install:</strong> Extract → Run install.bat as Admin → Done!<br>
<small>Supports all thermal printers • Auto-starts with Windows • One-click installation</small>
</div>
</div>
</div>
</div> <!-- Data Preview Card -->
<div class="card scan-table-card" style="min-height: 700px; width: calc(100% - 350px); margin: 0;">
@@ -330,6 +349,9 @@ document.getElementById('check-db-btn').addEventListener('click', function() {
// Initialize PDF generation functionality
addPDFGenerationHandler();
// Initialize print service
initializePrintService();
// Auto-select first row
setTimeout(() => {
const firstRow = document.querySelector('.print-module-table tbody tr');
@@ -396,6 +418,96 @@ function updateLabelPreview(order) {
document.getElementById('barcode-text').textContent = prodOrder;
}
// Initialize print service connection and load available printers
function initializePrintService() {
// Check service status and load printers
checkPrintServiceStatus()
.then(serviceStatus => {
if (serviceStatus) {
console.log('✅ Print service is available');
loadAvailablePrinters();
updateServiceStatusIndicator(true);
} else {
console.log('⚠️ Print service not available');
updateServiceStatusIndicator(false);
}
})
.catch(error => {
console.log('❌ Print service connection failed:', error);
updateServiceStatusIndicator(false);
});
}
// Load available printers from print service
function loadAvailablePrinters() {
fetch('http://localhost:8899/printers', {
method: 'GET',
mode: 'cors'
})
.then(response => response.json())
.then(data => {
const printerSelect = document.getElementById('printerSelect');
// Clear existing options except default ones
const defaultOptions = ['default', 'Epson TM-T20', 'Citizen CTS-310', 'custom'];
Array.from(printerSelect.options).forEach(option => {
if (!defaultOptions.includes(option.value)) {
option.remove();
}
});
// Add available printers
if (data.printers && data.printers.length > 0) {
data.printers.forEach(printer => {
// Don't add if already exists in default options
if (!defaultOptions.includes(printer.name)) {
const option = document.createElement('option');
option.value = printer.name;
option.textContent = `${printer.name}${printer.default ? ' (Default)' : ''}${printer.status !== 'ready' ? ' - Offline' : ''}`;
// Insert before "Other Printer..." option
const customOption = printerSelect.querySelector('option[value="custom"]');
printerSelect.insertBefore(option, customOption);
}
});
// Set default printer if available
const defaultPrinter = data.printers.find(p => p.default);
if (defaultPrinter) {
printerSelect.value = defaultPrinter.name;
}
}
console.log(`Loaded ${data.printers.length} printers from service`);
})
.catch(error => {
console.log('Could not load printers from service:', error);
});
}
// Update service status indicator
function updateServiceStatusIndicator(isAvailable) {
// Find or create status indicator
let statusIndicator = document.getElementById('service-status-indicator');
if (!statusIndicator) {
statusIndicator = document.createElement('div');
statusIndicator.id = 'service-status-indicator';
statusIndicator.style.cssText = 'font-size: 9px; color: #6c757d; margin-top: 5px; text-align: center;';
// Insert after printer selection
const printerSelection = document.getElementById('printerSelection');
printerSelection.appendChild(statusIndicator);
}
if (isAvailable) {
statusIndicator.innerHTML = '🟢 <strong>Print service connected</strong><br><small>Direct printing available</small>';
statusIndicator.style.color = '#28a745';
} else {
statusIndicator.innerHTML = '🔴 <strong>Print service offline</strong><br><small>Install and start the service for direct printing</small>';
statusIndicator.style.color = '#dc3545';
}
}
// PDF Generation System - No printer setup needed
// Labels are generated as PDF files for universal compatibility
function addPDFGenerationHandler() {
@@ -463,67 +575,114 @@ function handleDirectPrint(selectedRow) {
printerName = prompt('Enter your printer name:');
if (!printerName) return;
} else if (printerName === 'default') {
printerName = 'default';
printerName = ''; // Empty for default printer
}
console.log(`Direct printing to: ${printerName}`);
console.log(`Direct printing to: ${printerName || 'default printer'}`);
// Extract order data from selected row
const cells = selectedRow.querySelectorAll('td');
const orderData = {
order_id: parseInt(orderId),
comanda_productie: cells[1].textContent.trim(),
cod_articol: cells[2].textContent.trim(),
descr_com_prod: cells[3].textContent.trim(),
cantitate: parseInt(cells[4].textContent.trim()),
data_livrare: cells[5].textContent.trim(),
dimensiune: cells[6].textContent.trim(),
com_achiz_client: cells[7].textContent.trim(),
nr_linie_com_client: cells[8].textContent.trim(),
customer_name: cells[9].textContent.trim(),
customer_article_number: cells[10].textContent.trim()
};
// Print each label individually
for (let i = 1; i <= quantity; i++) {
const labelData = {
...orderData,
sequential_number: `${orderData.comanda_productie}-${i.toString().padStart(3, '0')}`,
current_label: i,
total_labels: quantity
};
// Encode data as base64 JSON
const jsonString = JSON.stringify(labelData);
const base64Data = btoa(unescape(encodeURIComponent(jsonString)));
// Create custom protocol URL
const printUrl = `recticel-print://${encodeURIComponent(printerName)}/${base64Data}`;
console.log(`Printing label ${i}/${quantity}: ${printUrl.substring(0, 100)}...`);
// Trigger direct print via custom protocol
try {
window.location.href = printUrl;
} catch (error) {
console.error(`Failed to print label ${i}:`, error);
alert(`❌ Failed to print label ${i}/${quantity}. Please check if the print service is installed.`);
return;
// Check if print service is available
checkPrintServiceStatus()
.then(serviceStatus => {
if (!serviceStatus) {
throw new Error('Print service is not available');
}
// Generate PDF first for printing
return generatePrintablePDF(orderId, true); // true for paper-saving mode
})
.then(pdfUrl => {
// Send PDF to print service
const printData = {
pdf_url: pdfUrl,
printer: printerName,
copies: 1,
order_id: parseInt(orderId),
paper_saving: true
};
return fetch('http://localhost:8899/print-pdf', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(printData)
});
})
.then(response => {
if (!response.ok) {
throw new Error(`Print service error: ${response.status}`);
}
return response.json();
})
.then(result => {
if (result.success) {
alert(`✅ Successfully sent ${quantity} labels to printer!\n📊 Order: ${prodOrder}\n🖨️ Printer: ${printerName || 'Default'}\n📄 Job ID: ${result.job_id || 'N/A'}`);
// Update database status and refresh table
updatePrintedStatus(orderId);
} else {
throw new Error(result.error || 'Unknown print error');
}
})
.catch(error => {
console.error('Direct print error:', error);
let errorMessage = '❌ Direct printing failed: ' + error.message;
if (error.message.includes('service is not available')) {
errorMessage += '\n\n💡 Solutions:\n' +
'1. Install the print service using the download link below\n' +
'2. Ensure the service is running (check Windows Services)\n' +
'3. Try restarting the print service\n' +
'4. Use PDF generation as alternative';
} else if (error.message.includes('fetch')) {
errorMessage += '\n\n💡 The print service may not be running.\n' +
'Please start the Quality Print Service from Windows Services.';
}
alert(errorMessage);
});
}
// Helper function to check print service status
function checkPrintServiceStatus() {
return fetch('http://localhost:8899/status', {
method: 'GET',
mode: 'cors'
})
.then(response => {
if (response.ok) {
return response.json().then(data => {
console.log('Print service status:', data);
return data.status === 'running';
});
}
// Small delay between labels to prevent overwhelming the printer
if (i < quantity) {
setTimeout(() => {}, 100);
return false;
})
.catch(error => {
console.log('Print service not available:', error.message);
return false;
});
}
// Helper function to generate PDF for printing
function generatePrintablePDF(orderId, paperSaving = true) {
return fetch(`/generate_labels_pdf/${orderId}/${paperSaving ? 'true' : 'false'}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
}
// Show success message
setTimeout(() => {
alert(`✅ Sent ${quantity} labels to printer: ${printerName}\n📊 Order: ${prodOrder}`);
// Update database status and refresh table
updatePrintedStatus(orderId);
}, 500);
})
.then(response => {
if (!response.ok) {
throw new Error(`Failed to generate PDF: ${response.status}`);
}
return response.blob();
})
.then(blob => {
// Create a temporary URL for the PDF
return URL.createObjectURL(blob);
});
}
function handlePDFGeneration(selectedRow) {