Add import labels functionality to labels module
- Created import_labels.py with CSV and Excel file processing - Implemented validation for order rows and date format handling - Added import-labels route with preview and save functionality - Created import_labels.html template with new app UI styling - Added import card to labels module index - Added openpyxl to requirements.txt for Excel support
This commit is contained in:
@@ -2,8 +2,12 @@
|
||||
Labels Module Routes
|
||||
Handles label printing pages and API endpoints
|
||||
"""
|
||||
from flask import Blueprint, render_template, session, redirect, url_for, jsonify, request
|
||||
from flask import Blueprint, render_template, session, redirect, url_for, jsonify, request, flash
|
||||
import logging
|
||||
import json
|
||||
import uuid
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from app.database import get_db
|
||||
from .print_module import (
|
||||
@@ -12,6 +16,11 @@ from .print_module import (
|
||||
update_order_printed_status,
|
||||
search_orders_by_cp_code
|
||||
)
|
||||
from .import_labels import (
|
||||
process_csv_file,
|
||||
process_excel_file,
|
||||
save_orders_to_database
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -54,6 +63,148 @@ def print_lost_labels():
|
||||
return render_template('modules/labels/print_lost_labels.html')
|
||||
|
||||
|
||||
@labels_bp.route('/import-labels', methods=['GET', 'POST'])
|
||||
def import_labels():
|
||||
"""Import labels data from CSV or Excel file"""
|
||||
if 'user_id' not in session:
|
||||
return redirect(url_for('main.login'))
|
||||
|
||||
if request.method == 'POST':
|
||||
action = request.form.get('action', 'preview')
|
||||
|
||||
if action == 'preview':
|
||||
# Handle file upload and show preview
|
||||
if 'file' not in request.files:
|
||||
flash('No file selected', 'error')
|
||||
return redirect(request.url)
|
||||
|
||||
file = request.files['file']
|
||||
|
||||
if file.filename == '':
|
||||
flash('No file selected', 'error')
|
||||
return redirect(request.url)
|
||||
|
||||
filename_lower = file.filename.lower()
|
||||
|
||||
# Check file type
|
||||
if not (filename_lower.endswith('.csv') or filename_lower.endswith('.xlsx') or filename_lower.endswith('.xls')):
|
||||
flash('Please upload a CSV or Excel file (.csv, .xlsx, .xls)', 'error')
|
||||
return redirect(request.url)
|
||||
|
||||
try:
|
||||
# Save file temporarily
|
||||
upload_id = str(uuid.uuid4())
|
||||
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=os.path.splitext(file.filename)[1])
|
||||
file.save(temp_file.name)
|
||||
temp_file.close()
|
||||
|
||||
# Process file
|
||||
if filename_lower.endswith('.csv'):
|
||||
orders_data, errors, warnings = process_csv_file(temp_file.name)
|
||||
else:
|
||||
orders_data, errors, warnings = process_excel_file(temp_file.name)
|
||||
|
||||
# Clean up temp file
|
||||
try:
|
||||
os.unlink(temp_file.name)
|
||||
except:
|
||||
pass
|
||||
|
||||
# Save orders data to temp file
|
||||
temp_data_file = f'/tmp/upload_{upload_id}.json'
|
||||
with open(temp_data_file, 'w') as f:
|
||||
json.dump(orders_data, f)
|
||||
|
||||
# Store in session
|
||||
session['upload_id'] = upload_id
|
||||
session['import_filename'] = file.filename
|
||||
session.modified = True
|
||||
|
||||
# Get headers for preview
|
||||
database_fields = [
|
||||
'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'
|
||||
]
|
||||
|
||||
headers = [field for field in database_fields if field in orders_data[0].keys()] if orders_data else database_fields
|
||||
preview_data = orders_data[:10]
|
||||
|
||||
# Flash any warnings/errors
|
||||
for warning in warnings[:5]:
|
||||
flash(warning, 'warning')
|
||||
if len(warnings) > 5:
|
||||
flash(f'... and {len(warnings) - 5} more warnings', 'warning')
|
||||
|
||||
for error in errors[:10]:
|
||||
flash(error, 'error')
|
||||
if len(errors) > 10:
|
||||
flash(f'... and {len(errors) - 10} more errors', 'error')
|
||||
|
||||
if not orders_data:
|
||||
flash('No valid data found in file', 'error')
|
||||
return redirect(request.url)
|
||||
|
||||
return render_template('modules/labels/import_labels.html',
|
||||
preview_data=preview_data,
|
||||
headers=headers,
|
||||
show_preview=True,
|
||||
filename=file.filename,
|
||||
total_orders=len(orders_data))
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing import file: {e}")
|
||||
flash(f'Error processing file: {str(e)}', 'error')
|
||||
return redirect(request.url)
|
||||
|
||||
elif action == 'save':
|
||||
# Save data to database
|
||||
upload_id = session.get('upload_id')
|
||||
|
||||
if not upload_id:
|
||||
flash('No data to save. Please upload a file first.', 'error')
|
||||
return redirect(url_for('labels.import_labels'))
|
||||
|
||||
try:
|
||||
# Load orders data from temp file
|
||||
temp_data_file = f'/tmp/upload_{upload_id}.json'
|
||||
with open(temp_data_file, 'r') as f:
|
||||
orders_data = json.load(f)
|
||||
|
||||
# Save to database
|
||||
inserted_count, errors = save_orders_to_database(orders_data)
|
||||
|
||||
# Clean up
|
||||
try:
|
||||
os.unlink(temp_data_file)
|
||||
except:
|
||||
pass
|
||||
|
||||
session.pop('upload_id', None)
|
||||
session.pop('import_filename', None)
|
||||
session.modified = True
|
||||
|
||||
# Flash results
|
||||
if errors:
|
||||
for error in errors[:5]:
|
||||
flash(error, 'error')
|
||||
if len(errors) > 5:
|
||||
flash(f'... and {len(errors) - 5} more errors', 'error')
|
||||
flash(f'Imported {inserted_count} orders with {len(errors)} errors', 'warning')
|
||||
else:
|
||||
flash(f'Successfully imported {inserted_count} orders for labels', 'success')
|
||||
|
||||
return redirect(url_for('labels.import_labels'))
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error saving import data: {e}")
|
||||
flash(f'Error saving data: {str(e)}', 'error')
|
||||
return redirect(url_for('labels.import_labels'))
|
||||
|
||||
# GET request - show the import form
|
||||
return render_template('modules/labels/import_labels.html')
|
||||
|
||||
|
||||
@labels_bp.route('/help/<page>', methods=['GET'])
|
||||
def help(page='index'):
|
||||
"""Help page for labels module"""
|
||||
|
||||
Reference in New Issue
Block a user