commit node js
This commit is contained in:
104
electron_pos_analysis.py
Normal file
104
electron_pos_analysis.py
Normal file
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Analysis: electron-pos-printer vs Other Solutions
|
||||
Comprehensive comparison for thermal printer integration
|
||||
"""
|
||||
|
||||
print("🔍 ELECTRON-POS-PRINTER ANALYSIS")
|
||||
print("=" * 60)
|
||||
print()
|
||||
|
||||
print("📊 SOLUTION COMPARISON:")
|
||||
print()
|
||||
|
||||
solutions = {
|
||||
"Windows Service": {
|
||||
"pros": ["Universal browser support", "Background operation", "No user interaction"],
|
||||
"cons": ["Complex installation", "Windows only", "Service management issues", "Firewall/security concerns"],
|
||||
"complexity": "High",
|
||||
"reliability": "Medium",
|
||||
"user_experience": "Poor (complex setup)"
|
||||
},
|
||||
"Chrome Extension": {
|
||||
"pros": ["Better integration", "No installation complexity", "Chrome Web Store distribution"],
|
||||
"cons": ["Chrome/Edge only", "Limited printer access", "Manifest V3 restrictions", "Native messaging needed"],
|
||||
"complexity": "High",
|
||||
"reliability": "Medium",
|
||||
"user_experience": "Medium (browser dependent)"
|
||||
},
|
||||
"Electron POS Printer": {
|
||||
"pros": [
|
||||
"Direct printer communication",
|
||||
"Rich formatting (text, barcodes, QR, images, tables)",
|
||||
"Multiple paper sizes (80mm, 58mm, etc.)",
|
||||
"Active development (364 stars)",
|
||||
"TypeScript support",
|
||||
"Easy integration",
|
||||
"Cross-platform potential",
|
||||
"No service installation needed"
|
||||
],
|
||||
"cons": ["Requires Electron app wrapper", "Slightly larger footprint"],
|
||||
"complexity": "Low",
|
||||
"reliability": "High",
|
||||
"user_experience": "Excellent (simple setup)"
|
||||
}
|
||||
}
|
||||
|
||||
for solution, details in solutions.items():
|
||||
print(f"🏗️ {solution.upper()}:")
|
||||
print(f" ✅ Pros: {', '.join(details['pros'])}")
|
||||
print(f" ❌ Cons: {', '.join(details['cons'])}")
|
||||
print(f" 🔧 Complexity: {details['complexity']}")
|
||||
print(f" 🎯 Reliability: {details['reliability']}")
|
||||
print(f" 👤 UX: {details['user_experience']}")
|
||||
print()
|
||||
|
||||
print("🎯 RECOMMENDATION: ELECTRON-POS-PRINTER")
|
||||
print("=" * 60)
|
||||
print()
|
||||
|
||||
print("✅ WHY ELECTRON-POS-PRINTER IS THE BEST CHOICE:")
|
||||
print(" 1. 🎨 Rich formatting capabilities (perfect for our labels)")
|
||||
print(" 2. 🖨️ Direct thermal printer support")
|
||||
print(" 3. 📏 Multiple paper sizes (58mm, 80mm thermal printers)")
|
||||
print(" 4. 🔧 Simple installation - just package the Electron app")
|
||||
print(" 5. 🚀 Active project with 364 stars and regular updates")
|
||||
print(" 6. 📱 Can create standalone desktop app for printing")
|
||||
print(" 7. 🔗 Easy web integration via IPC or HTTP API")
|
||||
print(" 8. 🎯 Designed specifically for POS/receipt printing")
|
||||
print()
|
||||
|
||||
print("🏗️ IMPLEMENTATION STRATEGY:")
|
||||
print(" 1. Create Electron wrapper app around our Flask web interface")
|
||||
print(" 2. Use electron-pos-printer for all thermal printing")
|
||||
print(" 3. Keep PDF generation as fallback for non-thermal printers")
|
||||
print(" 4. Package as single executable for easy deployment")
|
||||
print()
|
||||
|
||||
print("📋 IMPLEMENTATION STEPS:")
|
||||
print(" ✨ Step 1: Create Electron main process")
|
||||
print(" 🖨️ Step 2: Integrate electron-pos-printer")
|
||||
print(" 🔗 Step 3: Add IPC communication with web interface")
|
||||
print(" 📦 Step 4: Package for distribution")
|
||||
print(" 🧪 Step 5: Test with thermal printers")
|
||||
print()
|
||||
|
||||
print("🔥 KEY FEATURES WE CAN IMPLEMENT:")
|
||||
print(" • Direct thermal printing without PDF")
|
||||
print(" • Barcode generation (Code128, Code39, EAN, etc.)")
|
||||
print(" • QR code generation")
|
||||
print(" • Rich text formatting")
|
||||
print(" • Image printing (logos, etc.)")
|
||||
print(" • Table layouts")
|
||||
print(" • Multiple copies")
|
||||
print(" • Print preview")
|
||||
print(" • Paper size optimization")
|
||||
print()
|
||||
|
||||
print("✅ VERDICT: This is the BEST solution!")
|
||||
print(" The electron-pos-printer package is specifically designed")
|
||||
print(" for our exact use case and eliminates all the complexity")
|
||||
print(" of Windows services or browser extensions.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
import mariadb
|
||||
from datetime import datetime, timedelta
|
||||
from flask import Blueprint, render_template, redirect, url_for, request, flash, session, current_app, jsonify
|
||||
from flask import Blueprint, render_template, redirect, url_for, request, flash, session, current_app, jsonify, send_from_directory
|
||||
from .models import User
|
||||
from . import db
|
||||
from reportlab.lib.pagesizes import letter
|
||||
@@ -2106,6 +2106,30 @@ def download_print_service():
|
||||
print(f"DEBUG: Error downloading print service: {e}")
|
||||
return jsonify({'error': 'Failed to download print service'}), 500
|
||||
|
||||
@bp.route('/download/desktop-app')
|
||||
def download_desktop_app():
|
||||
"""Download the Quality Print Desktop v1.0.0 application"""
|
||||
try:
|
||||
# Path to the desktop app file
|
||||
downloads_path = os.path.join(current_app.root_path, 'static', 'downloads')
|
||||
filename = 'Quality_Print_Desktop_v1.0.0.zip'
|
||||
|
||||
# Check if the zip file exists
|
||||
full_path = os.path.join(downloads_path, filename)
|
||||
|
||||
if not os.path.exists(full_path):
|
||||
return jsonify({
|
||||
'error': 'Desktop app package not found',
|
||||
'message': 'Quality Print Desktop v1.0.0 is not available',
|
||||
'suggestion': 'Please contact the administrator'
|
||||
}), 404
|
||||
|
||||
return send_from_directory(downloads_path, filename, as_attachment=True)
|
||||
|
||||
except Exception as e:
|
||||
print(f"DEBUG: Error downloading desktop app: {e}")
|
||||
return jsonify({'error': 'Failed to download desktop app'}), 500
|
||||
|
||||
@bp.route('/get_order_data/<int:order_id>', methods=['GET'])
|
||||
def get_order_data(order_id):
|
||||
"""Get specific order data for preview"""
|
||||
|
||||
@@ -207,20 +207,36 @@
|
||||
|
||||
<!-- 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>
|
||||
<!-- Electron App (Recommended) -->
|
||||
<div style="background: #d4edda; border: 1px solid #c3e6cb; border-radius: 6px; padding: 12px; margin-bottom: 10px;">
|
||||
<div style="font-size: 11px; color: #155724; margin-bottom: 8px;">
|
||||
<strong>🖥️ Quality Print Desktop v1.0.0 (RECOMMENDED)</strong>
|
||||
</div>
|
||||
<div style="font-size: 10px; color: #495057; margin-bottom: 10px; line-height: 1.3;">
|
||||
Professional desktop app with built-in thermal printing • Direct hardware access • Rich formatting
|
||||
</div>
|
||||
<button onclick="downloadElectronApp()" class="btn btn-success btn-sm" style="font-size: 10px; padding: 4px 12px; margin-right: 5px;">
|
||||
📥 Download Desktop App (98MB)
|
||||
</button>
|
||||
<small style="color: #28a745; font-weight: bold;">✅ READY!</small>
|
||||
</div>
|
||||
|
||||
<!-- Windows Service (Deprecated) -->
|
||||
<div style="background: #f8d7da; border: 1px solid #f5c6cb; border-radius: 6px; padding: 12px; margin-bottom: 10px;">
|
||||
<div style="font-size: 11px; color: #721c24; margin-bottom: 8px;">
|
||||
<strong>📦 Windows Print Service (DEPRECATED)</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
|
||||
Legacy background service • Limited features • Use desktop app instead
|
||||
</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 href="{{ url_for('main.download_print_service') }}?package=complete" class="btn btn-outline-secondary btn-sm" download style="font-size: 10px; padding: 4px 12px; text-decoration: none;">
|
||||
📥 Download Legacy Service
|
||||
</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>
|
||||
<strong>🏆 Desktop App Benefits:</strong> Direct thermal printing • Rich barcodes/QR codes • Better reliability<br>
|
||||
<small>✨ Now includes: electron-pos-printer • One-click install • Cross-platform support</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -580,18 +596,187 @@ function handleDirectPrint(selectedRow) {
|
||||
|
||||
console.log(`Direct printing to: ${printerName || 'default printer'}`);
|
||||
|
||||
// Check if print service is available
|
||||
checkPrintServiceStatus()
|
||||
.then(serviceStatus => {
|
||||
if (!serviceStatus) {
|
||||
throw new Error('Print service is not available');
|
||||
// Extract order data from selected row
|
||||
const cells = selectedRow.querySelectorAll('td');
|
||||
const orderData = {
|
||||
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()
|
||||
};
|
||||
|
||||
// Check for Electron thermal printing first (best option)
|
||||
if (window.ThermalPrinter) {
|
||||
console.log('🔥 Using Electron thermal printer');
|
||||
handleElectronThermalPrint(orderData, printerName, quantity, prodOrder);
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate PDF first for printing
|
||||
return generatePrintablePDF(orderId, true); // true for paper-saving mode
|
||||
// Fallback to Windows service (if available)
|
||||
checkPrintServiceStatus()
|
||||
.then(serviceStatus => {
|
||||
if (serviceStatus) {
|
||||
console.log('🖨️ Using Windows print service');
|
||||
return handleServicePrint(orderId, printerName, quantity, prodOrder);
|
||||
} else {
|
||||
throw new Error('No print service available. Please install the Quality Print Desktop app or Windows service.');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Direct print error:', error);
|
||||
|
||||
let errorMessage = '❌ Direct printing failed: ' + error.message;
|
||||
|
||||
if (error.message.includes('service') || error.message.includes('available')) {
|
||||
errorMessage += '\n\n💡 Solutions:\n' +
|
||||
'1. Download and install Quality Print Desktop app (recommended)\n' +
|
||||
'2. Install the Windows print service\n' +
|
||||
'3. Use PDF generation as alternative';
|
||||
}
|
||||
|
||||
alert(errorMessage);
|
||||
});
|
||||
}
|
||||
|
||||
// Handle Electron thermal printing (best option)
|
||||
function handleElectronThermalPrint(orderData, printerName, quantity, prodOrder) {
|
||||
const button = document.getElementById('print-label-btn');
|
||||
const originalText = button.textContent;
|
||||
button.textContent = 'Printing...';
|
||||
button.disabled = true;
|
||||
|
||||
// Print each label sequentially
|
||||
printSequentialLabels(orderData, printerName, quantity, 0)
|
||||
.then(() => {
|
||||
alert(`✅ Successfully printed ${quantity} labels!\n📊 Order: ${prodOrder}\n🖨️ Printer: ${printerName || 'Default Printer'}\n🔥 Using Electron Thermal Printing`);
|
||||
|
||||
// Update database status
|
||||
updatePrintedStatus(orderData.id);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Electron thermal print error:', error);
|
||||
alert(`❌ Thermal printing failed: ${error.message}\n\n💡 Try using PDF generation instead.`);
|
||||
})
|
||||
.finally(() => {
|
||||
button.textContent = originalText;
|
||||
button.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
// Print labels sequentially for better reliability
|
||||
async function printSequentialLabels(orderData, printerName, totalQuantity, currentIndex) {
|
||||
if (currentIndex >= totalQuantity) {
|
||||
return; // All labels printed
|
||||
}
|
||||
|
||||
const labelNumber = currentIndex + 1;
|
||||
const sequentialId = `${orderData.comanda_productie}-${labelNumber.toString().padStart(3, '0')}`;
|
||||
|
||||
// Generate label data for this specific label
|
||||
const labelData = [
|
||||
{
|
||||
type: 'text',
|
||||
value: 'INNOFA ROMANIA SRL',
|
||||
style: { fontWeight: 'bold', fontSize: '12px', textAlign: 'center', marginBottom: '5px' }
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: orderData.customer_name || 'N/A',
|
||||
style: { fontSize: '11px', textAlign: 'center', marginBottom: '3px' }
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: '─'.repeat(32),
|
||||
style: { textAlign: 'center', fontSize: '8px', marginBottom: '2px' }
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: `Quantity: ${orderData.cantitate || '0'}`,
|
||||
style: { fontSize: '10px', marginBottom: '2px' }
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: `Customer Order: ${orderData.com_achiz_client || 'N/A'}-${orderData.nr_linie_com_client || '00'}`,
|
||||
style: { fontSize: '10px', marginBottom: '2px' }
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: `Delivery: ${orderData.data_livrare || 'N/A'}`,
|
||||
style: { fontSize: '10px', marginBottom: '2px' }
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: `Size: ${orderData.dimensiune || 'N/A'}`,
|
||||
style: { fontSize: '10px', marginBottom: '2px' }
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: `Article: ${orderData.customer_article_number || 'N/A'}`,
|
||||
style: { fontSize: '10px', marginBottom: '3px' }
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: '─'.repeat(32),
|
||||
style: { textAlign: 'center', fontSize: '8px', marginBottom: '3px' }
|
||||
},
|
||||
{
|
||||
type: 'barCode',
|
||||
value: sequentialId,
|
||||
height: 40,
|
||||
width: 2,
|
||||
displayValue: true,
|
||||
fontsize: 8,
|
||||
style: { textAlign: 'center', marginBottom: '5px' }
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: `Label ${labelNumber}/${totalQuantity}`,
|
||||
style: { fontSize: '8px', textAlign: 'center', marginBottom: '5px' }
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
value: ' ', // Add spacing
|
||||
style: { fontSize: '6px' }
|
||||
}
|
||||
];
|
||||
|
||||
const printOptions = {
|
||||
printerName: printerName || 'default',
|
||||
pageSize: '80mm',
|
||||
margin: '2mm 2mm 2mm 2mm',
|
||||
copies: 1,
|
||||
silent: true,
|
||||
preview: false,
|
||||
timeOutPerLine: 200
|
||||
};
|
||||
|
||||
console.log(`🏷️ Printing label ${labelNumber}/${totalQuantity}: ${sequentialId}`);
|
||||
|
||||
try {
|
||||
// Print this label
|
||||
await window.ThermalPrinter.print(labelData, printOptions);
|
||||
|
||||
// Small delay between labels
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
|
||||
// Print next label
|
||||
return printSequentialLabels(orderData, printerName, totalQuantity, currentIndex + 1);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to print label ${labelNumber}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Windows service printing (fallback)
|
||||
function handleServicePrint(orderId, printerName, quantity, prodOrder) {
|
||||
return generatePrintablePDF(orderId, true) // true for paper-saving mode
|
||||
.then(pdfUrl => {
|
||||
// Send PDF to print service
|
||||
const printData = {
|
||||
pdf_url: pdfUrl,
|
||||
printer: printerName,
|
||||
@@ -616,31 +801,13 @@ function handleDirectPrint(selectedRow) {
|
||||
})
|
||||
.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'}`);
|
||||
alert(`✅ Successfully sent ${quantity} labels to printer!\n📊 Order: ${prodOrder}\n<EFBFBD>️ Printer: ${printerName || 'Default'}\n📄 Job ID: ${result.job_id || 'N/A'}`);
|
||||
|
||||
// Update database status and refresh table
|
||||
updatePrintedStatus(orderId);
|
||||
updatePrintedStatus(parseInt(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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -929,6 +1096,20 @@ function clearLabelPreview() {
|
||||
document.getElementById('vertical-barcode-text').textContent = '000000-00';
|
||||
}
|
||||
|
||||
// Download Electron app function
|
||||
function downloadElectronApp() {
|
||||
// Download the Quality Print Desktop v1.0.0
|
||||
const link = document.createElement('a');
|
||||
link.href = '/download/desktop-app';
|
||||
link.download = 'Quality_Print_Desktop_v1.0.0.zip';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
|
||||
// Show success message
|
||||
showNotification('<27> Quality Print Desktop v1.0.0 download started!', 'success');
|
||||
}
|
||||
|
||||
document.getElementById('print-label-btn').addEventListener('click', function() {
|
||||
console.log('Generate PDF logic here');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user