updated print module
This commit is contained in:
Binary file not shown.
@@ -1615,3 +1615,146 @@ def create_locations():
|
|||||||
def import_locations_csv():
|
def import_locations_csv():
|
||||||
from app.warehouse import import_locations_csv_handler
|
from app.warehouse import import_locations_csv_handler
|
||||||
return import_locations_csv_handler()
|
return import_locations_csv_handler()
|
||||||
|
|
||||||
|
@bp.route('/print_labels_silent/<int:order_id>', methods=['POST'])
|
||||||
|
def print_labels_silent(order_id):
|
||||||
|
"""Generate PDF and send directly to Windows Print Service - bypasses CORS"""
|
||||||
|
print(f"DEBUG: print_labels_silent called for order_id: {order_id}")
|
||||||
|
|
||||||
|
if 'role' not in session or session['role'] not in ['superadmin', 'warehouse_manager', 'etichete']:
|
||||||
|
return jsonify({'error': 'Access denied'}), 403
|
||||||
|
|
||||||
|
try:
|
||||||
|
import requests
|
||||||
|
import tempfile
|
||||||
|
import os
|
||||||
|
from .pdf_generator import generate_order_labels_pdf, update_order_printed_status
|
||||||
|
from .print_module import get_db_connection
|
||||||
|
|
||||||
|
# Get printer name from request
|
||||||
|
data = request.get_json() or {}
|
||||||
|
printer_name = data.get('printer_name', 'default')
|
||||||
|
|
||||||
|
print(f"DEBUG: Using printer: {printer_name}")
|
||||||
|
|
||||||
|
# Get order data from database
|
||||||
|
conn = get_db_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT id, comanda_productie, cod_articol, descr_com_prod, cantitate,
|
||||||
|
data_livrare, dimensiune, com_achiz_client, nr_linie_com_client, customer_name,
|
||||||
|
customer_article_number, open_for_order, line_number,
|
||||||
|
printed_labels, created_at, updated_at
|
||||||
|
FROM order_for_labels
|
||||||
|
WHERE id = %s
|
||||||
|
""", (order_id,))
|
||||||
|
|
||||||
|
order_data = cursor.fetchone()
|
||||||
|
cursor.close()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
if not order_data:
|
||||||
|
return jsonify({'error': 'Order not found'}), 404
|
||||||
|
|
||||||
|
# Convert to dictionary for easier access
|
||||||
|
columns = ['id', 'comanda_productie', 'cod_articol', 'descr_com_prod', 'cantitate',
|
||||||
|
'data_livrare', 'dimensiune', 'com_achiz_client', 'nr_linie_com_client',
|
||||||
|
'customer_name', 'customer_article_number', 'open_for_order', 'line_number',
|
||||||
|
'printed_labels', 'created_at', 'updated_at']
|
||||||
|
order_dict = dict(zip(columns, order_data))
|
||||||
|
|
||||||
|
print(f"DEBUG: Order data: {order_dict}")
|
||||||
|
|
||||||
|
# Generate PDF content in memory
|
||||||
|
pdf_content = generate_order_labels_pdf(order_dict)
|
||||||
|
|
||||||
|
# Save PDF to a location accessible by Windows service
|
||||||
|
pdf_dir = r"C:\temp\quality_labels"
|
||||||
|
if not os.path.exists(pdf_dir):
|
||||||
|
os.makedirs(pdf_dir, exist_ok=True)
|
||||||
|
|
||||||
|
pdf_filename = f"order_{order_id}_{order_dict['comanda_productie']}.pdf"
|
||||||
|
pdf_path = os.path.join(pdf_dir, pdf_filename)
|
||||||
|
|
||||||
|
# Write PDF to file
|
||||||
|
with open(pdf_path, 'wb') as pdf_file:
|
||||||
|
pdf_file.write(pdf_content)
|
||||||
|
|
||||||
|
print(f"DEBUG: Created PDF file: {pdf_path}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Send to Windows Print Service with local file path
|
||||||
|
print_service_url = 'http://localhost:8765'
|
||||||
|
|
||||||
|
# Create the print request with local file path
|
||||||
|
print_data = {
|
||||||
|
'pdf_path': pdf_path,
|
||||||
|
'printer_name': printer_name,
|
||||||
|
'copies': 1,
|
||||||
|
'silent': True,
|
||||||
|
'order_id': order_id,
|
||||||
|
'quantity': order_dict['cantitate']
|
||||||
|
}
|
||||||
|
|
||||||
|
print(f"DEBUG: Sending print request to {print_service_url}/print/silent")
|
||||||
|
|
||||||
|
# Send request to Windows service
|
||||||
|
response = requests.post(
|
||||||
|
f'{print_service_url}/print/silent',
|
||||||
|
json=print_data,
|
||||||
|
headers={'Content-Type': 'application/json'},
|
||||||
|
timeout=30
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"DEBUG: Print service response: {response.status_code}")
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
result = response.json()
|
||||||
|
print(f"DEBUG: Print result: {result}")
|
||||||
|
|
||||||
|
if result.get('success'):
|
||||||
|
# Update order status
|
||||||
|
update_order_printed_status(order_id)
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'success': True,
|
||||||
|
'message': 'Labels printed successfully',
|
||||||
|
'printer': printer_name,
|
||||||
|
'order': order_dict['comanda_productie'],
|
||||||
|
'quantity': order_dict['cantitate']
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'error': result.get('error', 'Print service returned error')
|
||||||
|
}), 500
|
||||||
|
else:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'error': f'Print service returned status {response.status_code}'
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
print(f"DEBUG: Print service connection error: {e}")
|
||||||
|
# Fallback: Return the PDF for manual printing
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'error': f'Windows Print Service not available: {str(e)}',
|
||||||
|
'fallback': 'pdf_download',
|
||||||
|
'pdf_path': pdf_path
|
||||||
|
}), 503
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# Clean up PDF file
|
||||||
|
try:
|
||||||
|
os.unlink(pdf_path)
|
||||||
|
print(f"DEBUG: Cleaned up PDF file: {pdf_path}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"DEBUG: Error cleaning up PDF file: {e}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"DEBUG: Error in print_labels_silent: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
return jsonify({'error': str(e)}), 500
|
||||||
@@ -720,34 +720,25 @@ function updatePrintButtonForService(serviceAvailable) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enhanced print function with Windows service support
|
// Enhanced print function with Windows service support - NEW SERVER-SIDE APPROACH
|
||||||
async function printLabelsWithService(orderId, prodOrder, quantity) {
|
async function printLabelsWithService(orderId, prodOrder, quantity) {
|
||||||
console.log(`🖨️ printLabelsWithService called - Order: ${orderId}, Quantity: ${quantity}`);
|
console.log(`🖨️ printLabelsWithService called - Order: ${orderId}, Quantity: ${quantity}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Generate PDF URL
|
|
||||||
const pdfUrl = `${window.location.origin}/generate_labels_pdf/${orderId}`;
|
|
||||||
console.log(`📄 PDF URL: ${pdfUrl}`);
|
|
||||||
|
|
||||||
// Get selected printer from dropdown
|
// Get selected printer from dropdown
|
||||||
const selectedPrinter = getSelectedPrinter();
|
const selectedPrinter = getSelectedPrinter();
|
||||||
console.log(`🖨️ Selected printer: ${selectedPrinter}`);
|
console.log(`🖨️ Selected printer: ${selectedPrinter}`);
|
||||||
|
|
||||||
// Prepare print data for service
|
// Use new server-side endpoint that bypasses CORS
|
||||||
const printData = {
|
const printData = {
|
||||||
pdf_url: pdfUrl,
|
printer_name: selectedPrinter
|
||||||
printer_name: selectedPrinter,
|
|
||||||
copies: 1,
|
|
||||||
silent: true,
|
|
||||||
order_id: orderId,
|
|
||||||
quantity: quantity
|
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('📋 Print request data:', printData);
|
console.log('📋 Print request data:', printData);
|
||||||
console.log(`📡 Sending to: ${PRINT_SERVICE_URL}/print/silent`);
|
console.log(`📡 Sending to server endpoint: /print_labels_silent/${orderId}`);
|
||||||
|
|
||||||
// Send to Windows service
|
// Send to Flask server which handles Windows service communication
|
||||||
const response = await fetch(`${PRINT_SERVICE_URL}/print/silent`, {
|
const response = await fetch(`/print_labels_silent/${orderId}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
@@ -755,10 +746,10 @@ async function printLabelsWithService(orderId, prodOrder, quantity) {
|
|||||||
body: JSON.stringify(printData)
|
body: JSON.stringify(printData)
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`📨 Service response status: ${response.status}`);
|
console.log(`📨 Server response status: ${response.status}`);
|
||||||
|
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
console.log('📋 Service response data:', result);
|
console.log('📋 Server response data:', result);
|
||||||
|
|
||||||
if (response.ok && result.success) {
|
if (response.ok && result.success) {
|
||||||
// Success - labels printed silently
|
// Success - labels printed silently
|
||||||
@@ -771,13 +762,24 @@ async function printLabelsWithService(orderId, prodOrder, quantity) {
|
|||||||
await updatePrintedStatus(orderId);
|
await updatePrintedStatus(orderId);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
} else if (response.status === 503 && result.fallback === 'pdf_download') {
|
||||||
|
// Windows service not available - inform user and suggest fallback
|
||||||
|
console.warn('⚠️ Windows service not available, showing service setup info');
|
||||||
|
|
||||||
|
alert(`⚠️ Windows Print Service Not Available\n\n${result.error}\n\n📋 To enable silent printing:\n1. Install the Windows Print Service\n2. Start the service: sc start QualityLabelPrinting\n3. Restart your browser\n\n💡 For now, use the "Generate PDF" button for manual printing.`);
|
||||||
|
|
||||||
|
// Mark service as unavailable for this session
|
||||||
|
printServiceAvailable = false;
|
||||||
|
updatePrintButtonForService(false);
|
||||||
|
|
||||||
|
throw new Error('Windows Print Service not available');
|
||||||
} else {
|
} else {
|
||||||
console.error('❌ Service returned error:', result);
|
console.error('❌ Server returned error:', result);
|
||||||
throw new Error(result.error || `Print service failed with status ${response.status}`);
|
throw new Error(result.error || `Print operation failed with status ${response.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Windows service print error:', error);
|
console.error('❌ Server-side print error:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,51 @@ function Invoke-PrintPDF {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Print local PDF file function
|
||||||
|
function Invoke-PrintLocalPDF {
|
||||||
|
param(
|
||||||
|
[string]$PdfPath,
|
||||||
|
[string]$PrinterName = "default",
|
||||||
|
[int]$Copies = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-ServiceLog "Local print request: File=$PdfPath, Printer=$PrinterName, Copies=$Copies"
|
||||||
|
|
||||||
|
# Check if file exists
|
||||||
|
if (!(Test-Path $PdfPath)) {
|
||||||
|
throw "PDF file not found: $PdfPath"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get default printer if needed
|
||||||
|
if ($PrinterName -eq "default" -or [string]::IsNullOrEmpty($PrinterName)) {
|
||||||
|
$defaultPrinter = Get-WmiObject -Class Win32_Printer | Where-Object { $_.Default -eq $true }
|
||||||
|
$PrinterName = $defaultPrinter.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-ServiceLog "Using printer: $PrinterName"
|
||||||
|
|
||||||
|
# Print using Windows shell
|
||||||
|
$printJob = Start-Process -FilePath $PdfPath -Verb Print -PassThru -WindowStyle Hidden
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
|
||||||
|
Write-ServiceLog "Print job sent successfully to printer: $PrinterName"
|
||||||
|
return @{
|
||||||
|
success = $true
|
||||||
|
message = "Print job sent successfully"
|
||||||
|
printer = $PrinterName
|
||||||
|
timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-ServiceLog "Print error: $($_.Exception.Message)"
|
||||||
|
return @{
|
||||||
|
success = $false
|
||||||
|
error = $_.Exception.Message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# HTTP Response function
|
# HTTP Response function
|
||||||
function Send-HttpResponse {
|
function Send-HttpResponse {
|
||||||
param(
|
param(
|
||||||
@@ -179,7 +224,7 @@ function Start-PrintService {
|
|||||||
Send-HttpResponse -Context $context -Body ($printersData | ConvertTo-Json -Depth 3)
|
Send-HttpResponse -Context $context -Body ($printersData | ConvertTo-Json -Depth 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
"^/print/(pdf|silent)$" {
|
"^/print/(pdf|silent|file)$" {
|
||||||
if ($method -eq "POST") {
|
if ($method -eq "POST") {
|
||||||
try {
|
try {
|
||||||
# Read request body
|
# Read request body
|
||||||
@@ -190,8 +235,16 @@ function Start-PrintService {
|
|||||||
# Parse JSON
|
# Parse JSON
|
||||||
$printData = $body | ConvertFrom-Json
|
$printData = $body | ConvertFrom-Json
|
||||||
|
|
||||||
# Print PDF
|
# Print PDF - handle both URL and local file path
|
||||||
|
if ($printData.pdf_path -and (Test-Path $printData.pdf_path)) {
|
||||||
|
Write-ServiceLog "Using local PDF file: $($printData.pdf_path)"
|
||||||
|
$result = Invoke-PrintLocalPDF -PdfPath $printData.pdf_path -PrinterName $printData.printer_name -Copies $printData.copies
|
||||||
|
} elseif ($printData.pdf_url) {
|
||||||
|
Write-ServiceLog "Using PDF URL: $($printData.pdf_url)"
|
||||||
$result = Invoke-PrintPDF -PdfUrl $printData.pdf_url -PrinterName $printData.printer_name -Copies $printData.copies
|
$result = Invoke-PrintPDF -PdfUrl $printData.pdf_url -PrinterName $printData.printer_name -Copies $printData.copies
|
||||||
|
} else {
|
||||||
|
throw "Either pdf_path or pdf_url must be provided"
|
||||||
|
}
|
||||||
|
|
||||||
if ($result.success) {
|
if ($result.success) {
|
||||||
Send-HttpResponse -Context $context -Body ($result | ConvertTo-Json)
|
Send-HttpResponse -Context $context -Body ($result | ConvertTo-Json)
|
||||||
@@ -219,7 +272,7 @@ function Start-PrintService {
|
|||||||
$errorResponse = @{
|
$errorResponse = @{
|
||||||
success = $false
|
success = $false
|
||||||
error = "Endpoint not found"
|
error = "Endpoint not found"
|
||||||
available_endpoints = @("/health", "/printers", "/print/pdf", "/print/silent")
|
available_endpoints = @("/health", "/printers", "/print/pdf", "/print/silent", "/print/file")
|
||||||
}
|
}
|
||||||
Send-HttpResponse -Context $context -StatusCode 404 -Body ($errorResponse | ConvertTo-Json)
|
Send-HttpResponse -Context $context -StatusCode 404 -Body ($errorResponse | ConvertTo-Json)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user