Implement boxes management module with auto-numbered box creation

- Add boxes_crates database table with BIGINT IDs and 8-digit auto-numbered box_numbers
- Implement boxes CRUD operations (add, edit, update, delete, delete_multiple)
- Create boxes route handlers with POST actions for all operations
- Add boxes.html template with 3-panel layout matching warehouse locations module
- Implement barcode generation and printing with JsBarcode and QZ Tray integration
- Add browser print fallback for when QZ Tray is not available
- Simplify create box form to single button with auto-generation
- Fix JavaScript null reference errors with proper element validation
- Convert tuple data to dictionaries for Jinja2 template compatibility
- Register boxes blueprint in Flask app initialization
This commit is contained in:
Quality App Developer
2026-01-26 22:08:31 +02:00
parent 3c5a273a89
commit e1f3302c6b
37 changed files with 8429 additions and 66 deletions

View File

@@ -7,6 +7,8 @@ import hashlib
import secrets
from datetime import datetime, timedelta
from app.database import get_db
from app.modules.settings.stats import get_all_stats
from app.modules.settings.logs import get_log_files, get_log_content, get_log_file_path, get_log_statistics, search_in_logs
import subprocess
import os
import json
@@ -19,11 +21,30 @@ settings_bp = Blueprint('settings', __name__, url_prefix='/settings')
@settings_bp.route('/', methods=['GET'])
def settings_index():
"""Settings module main page"""
"""Settings module main page with app overview"""
if 'user_id' not in session:
return redirect(url_for('main.login'))
return render_template('modules/settings/index.html')
# Get all app statistics
try:
stats = get_all_stats()
except Exception as e:
logger.error(f"Error getting stats in settings_index: {e}", exc_info=True)
stats = {
'user_count': 0,
'database_size_mb': 0,
'logs_size_mb': 0,
'database_count': 0,
'backup_count': 0,
'printer_keys_count': 0,
'app_key_availability': {
'available': False,
'count': 0,
'status': 'Error loading data'
}
}
return render_template('modules/settings/index.html', stats=stats)
@settings_bp.route('/general', methods=['GET', 'POST'])
@@ -1254,3 +1275,100 @@ def toggle_backup_schedule(schedule_id):
except Exception as e:
return jsonify({'error': str(e)}), 500
# ============================================================================
# Log Explorer Routes
# ============================================================================
@settings_bp.route('/logs', methods=['GET'])
def logs_explorer():
"""Log explorer main page - list all log files"""
if 'user_id' not in session:
return redirect(url_for('main.login'))
try:
log_files = get_log_files()
log_stats = get_log_statistics()
return render_template('modules/settings/logs_explorer.html',
log_files=log_files,
log_stats=log_stats)
except Exception as e:
logger.error(f"Error loading logs explorer: {e}")
flash(f"Error loading logs: {str(e)}", 'error')
return render_template('modules/settings/logs_explorer.html',
log_files=[],
log_stats={})
@settings_bp.route('/logs/view/<filename>', methods=['GET'])
def view_log(filename):
"""View content of a specific log file"""
if 'user_id' not in session:
return redirect(url_for('main.login'))
try:
lines = request.args.get('lines', default=100, type=int)
log_data = get_log_content(filename, lines=lines)
if not log_data.get('success'):
flash(log_data.get('error', 'Error reading log file'), 'error')
return redirect(url_for('settings.logs_explorer'))
return render_template('modules/settings/view_log.html', log_data=log_data)
except Exception as e:
logger.error(f"Error viewing log {filename}: {e}")
flash(f"Error viewing log: {str(e)}", 'error')
return redirect(url_for('settings.logs_explorer'))
@settings_bp.route('/logs/download/<filename>', methods=['GET'])
def download_log(filename):
"""Download a log file"""
if 'user_id' not in session:
return redirect(url_for('main.login'))
try:
filepath = get_log_file_path(filename)
if not filepath:
flash('Invalid file or file not found', 'error')
return redirect(url_for('settings.logs_explorer'))
return send_file(
filepath,
as_attachment=True,
download_name=f"{filename}_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
)
except Exception as e:
logger.error(f"Error downloading log {filename}: {e}")
flash(f"Error downloading log: {str(e)}", 'error')
return redirect(url_for('settings.logs_explorer'))
@settings_bp.route('/logs/search', methods=['GET'])
def search_logs():
"""Search for terms in log files"""
if 'user_id' not in session:
return redirect(url_for('main.login'))
try:
search_term = request.args.get('q', '').strip()
filename = request.args.get('file', default=None)
results = []
if search_term:
results = search_in_logs(search_term, filename=filename)
log_files = get_log_files()
return render_template('modules/settings/search_logs.html',
search_term=search_term,
results=results,
log_files=log_files,
selected_file=filename)
except Exception as e:
logger.error(f"Error searching logs: {e}")
flash(f"Error searching logs: {str(e)}", 'error')
return redirect(url_for('settings.logs_explorer'))