Files
quality_app-v2/app/__init__.py
Quality App Developer 2f6bb5d029 feat: Migrate label printing module from legacy app
- Created labels module with complete structure in app/modules/labels/
- Implemented print_module.py with database functions:
  * get_unprinted_orders_data() - Retrieve unprinted orders from database
  * get_printed_orders_data() - Retrieve printed orders from database
  * update_order_printed_status() - Mark orders as printed
  * search_orders_by_cp_code() - Search orders by production code
- Created routes.py with Flask Blueprint and API endpoints:
  * GET /labels/ - Module home page with feature launchers
  * GET /labels/print-module - Main label printing interface
  * GET /labels/print-lost-labels - Lost label reprinting interface
  * GET /labels/api/unprinted-orders - API for unprinted orders
  * GET /labels/api/printed-orders - API for printed orders
  * POST /labels/api/search-orders - Search orders API
  * POST /labels/api/update-printed-status/<id> - Update status API
- Migrated HTML templates from legacy app with theme support:
  * print_module.html - Thermal label printing with QZ Tray integration
  * print_lost_labels.html - Lost label search and reprint interface
  * Added comprehensive CSS variables for dark/light mode theming
  * Preserved all original JavaScript functionality for printing
- Created index.html module home page with feature launchers
- Registered labels blueprint in app/__init__.py with /labels prefix
- Added 'Label Printing' module card to dashboard with print icon

All functionality preserved from original implementation:
- QZ Tray thermal printer integration
- JsBarcode barcode generation (horizontal + vertical)
- PDF export fallback
- Session-based authentication for all routes
- Database integration with proper error handling
2026-02-02 01:18:54 +02:00

203 lines
6.2 KiB
Python

"""
Quality App v2 - Flask Application Factory
Robust, modular application with login, dashboard, and multiple modules
"""
from flask import Flask
from flask_session import Session
from datetime import datetime, timedelta
import os
import logging
from logging.handlers import RotatingFileHandler
def create_app(config=None):
"""
Application factory function
Creates and configures the Flask application
"""
app = Flask(__name__)
# Load configuration
if config is None:
from app.config import Config
config = Config
app.config.from_object(config)
# Setup logging
setup_logging(app)
logger = logging.getLogger(__name__)
logger.info("=" * 80)
logger.info("Flask App Initialization Started")
logger.info("=" * 80)
# Configure session
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=8)
app.config['SESSION_COOKIE_SECURE'] = False # Set True in production with HTTPS
app.config['SESSION_COOKIE_HTTPONLY'] = True
app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'
app.config['SESSION_COOKIE_NAME'] = 'quality_app_session'
app.config['SESSION_REFRESH_EACH_REQUEST'] = True
# Use filesystem for session storage (works with multiple gunicorn workers)
sessions_dir = os.path.join(app.config.get('LOG_DIR', '/app/data/logs'), '..', 'sessions')
os.makedirs(sessions_dir, exist_ok=True)
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SESSION_FILE_DIR'] = sessions_dir
app.config['SESSION_FILE_THRESHOLD'] = 500
# Initialize Flask-Session
Session(app)
# Initialize database connection
logger.info("Initializing database connection...")
from app.database import init_db, close_db
init_db(app)
app.teardown_appcontext(close_db)
# Register blueprints
logger.info("Registering blueprints...")
register_blueprints(app)
# Register error handlers
logger.info("Registering error handlers...")
register_error_handlers(app)
# Add template globals
app.jinja_env.globals['now'] = datetime.now
# Add context processor for app name
@app.context_processor
def inject_app_settings():
"""Inject app settings into all templates"""
try:
from app.database import get_db
conn = get_db()
cursor = conn.cursor()
cursor.execute(
"SELECT setting_value FROM application_settings WHERE setting_key = %s",
('app_name',)
)
result = cursor.fetchone()
cursor.close()
app_name = result[0] if result else 'Quality App v2'
except:
app_name = 'Quality App v2'
return {'app_name': app_name}
# Add before_request handlers
register_request_handlers(app)
# Initialize backup scheduler
logger.info("Initializing backup scheduler...")
try:
from app.scheduler import init_scheduler
init_scheduler(app)
except Exception as e:
logger.error(f"Failed to initialize backup scheduler: {e}")
logger.info("=" * 80)
logger.info("Flask App Initialization Completed Successfully")
logger.info("=" * 80)
return app
def setup_logging(app):
"""Configure application logging"""
log_dir = app.config.get('LOG_DIR', '/app/data/logs')
# Create log directory if it doesn't exist
if not os.path.exists(log_dir):
os.makedirs(log_dir, exist_ok=True)
# Configure rotating file handler
log_file = os.path.join(log_dir, 'app.log')
handler = RotatingFileHandler(
log_file,
maxBytes=10485760, # 10MB
backupCount=10
)
# Create formatter
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
handler.setFormatter(formatter)
# Set logging level
log_level = app.config.get('LOG_LEVEL', 'INFO')
handler.setLevel(getattr(logging, log_level))
# Add handler to app logger
app.logger.addHandler(handler)
app.logger.setLevel(getattr(logging, log_level))
def register_blueprints(app):
"""Register application blueprints"""
from app.routes import main_bp
from app.modules.quality.routes import quality_bp
from app.modules.settings.routes import settings_bp
from app.modules.warehouse.routes import warehouse_bp
from app.modules.warehouse.boxes_routes import boxes_bp
from app.modules.labels.routes import labels_bp
app.register_blueprint(main_bp)
app.register_blueprint(quality_bp, url_prefix='/quality')
app.register_blueprint(settings_bp, url_prefix='/settings')
app.register_blueprint(warehouse_bp, url_prefix='/warehouse')
app.register_blueprint(boxes_bp)
app.register_blueprint(labels_bp, url_prefix='/labels')
app.logger.info("Blueprints registered: main, quality, settings, warehouse, boxes, labels")
def register_error_handlers(app):
"""Register error handlers"""
@app.errorhandler(404)
def page_not_found(e):
from flask import render_template
return render_template('errors/404.html'), 404
@app.errorhandler(500)
def internal_error(e):
from flask import render_template
app.logger.error(f"Internal error: {e}")
return render_template('errors/500.html'), 500
@app.errorhandler(403)
def forbidden(e):
from flask import render_template
return render_template('errors/403.html'), 403
def register_request_handlers(app):
"""Register before/after request handlers"""
@app.before_request
def before_request():
"""Handle pre-request logic"""
from flask import session, request, redirect, url_for
# Skip authentication check for login and static files
if request.endpoint and (
request.endpoint in ['static', 'main.login', 'main.index'] or
request.path.startswith('/static/')
):
return None
# Check if user is logged in
if 'user_id' not in session:
return redirect(url_for('main.login'))
return None
@app.after_request
def after_request(response):
"""Handle post-request logic"""
return response