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
This commit is contained in:
128
app/modules/labels/routes.py
Normal file
128
app/modules/labels/routes.py
Normal file
@@ -0,0 +1,128 @@
|
||||
"""
|
||||
Labels Module Routes
|
||||
Handles label printing pages and API endpoints
|
||||
"""
|
||||
from flask import Blueprint, render_template, session, redirect, url_for, jsonify, request
|
||||
import logging
|
||||
|
||||
from .print_module import (
|
||||
get_unprinted_orders_data,
|
||||
get_printed_orders_data,
|
||||
update_order_printed_status,
|
||||
search_orders_by_cp_code
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
labels_bp = Blueprint('labels', __name__, url_prefix='/labels')
|
||||
|
||||
|
||||
@labels_bp.route('/', methods=['GET'])
|
||||
def labels_index():
|
||||
"""Labels module home page"""
|
||||
if 'user_id' not in session:
|
||||
return redirect(url_for('main.login'))
|
||||
|
||||
return render_template('modules/labels/index.html')
|
||||
|
||||
|
||||
@labels_bp.route('/print-module', methods=['GET'])
|
||||
def print_module():
|
||||
"""Label printing interface with thermal printer support"""
|
||||
if 'user_id' not in session:
|
||||
return redirect(url_for('main.login'))
|
||||
|
||||
return render_template('modules/labels/print_module.html')
|
||||
|
||||
|
||||
@labels_bp.route('/print-lost-labels', methods=['GET'])
|
||||
def print_lost_labels():
|
||||
"""Print lost/missing labels interface"""
|
||||
if 'user_id' not in session:
|
||||
return redirect(url_for('main.login'))
|
||||
|
||||
return render_template('modules/labels/print_lost_labels.html')
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# API Endpoints for Labels Module
|
||||
# ============================================================================
|
||||
|
||||
@labels_bp.route('/api/unprinted-orders', methods=['GET'], endpoint='api_unprinted_orders')
|
||||
def api_unprinted_orders():
|
||||
"""Get all unprinted orders for label printing"""
|
||||
if 'user_id' not in session:
|
||||
return jsonify({'success': False, 'error': 'Unauthorized'}), 401
|
||||
|
||||
try:
|
||||
limit = request.args.get('limit', 100, type=int)
|
||||
if limit > 500:
|
||||
limit = 500
|
||||
if limit < 1:
|
||||
limit = 1
|
||||
|
||||
orders = get_unprinted_orders_data(limit)
|
||||
return jsonify({'success': True, 'orders': orders, 'count': len(orders)}), 200
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting unprinted orders: {e}")
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
|
||||
@labels_bp.route('/api/printed-orders', methods=['GET'], endpoint='api_printed_orders')
|
||||
def api_printed_orders():
|
||||
"""Get all printed orders"""
|
||||
if 'user_id' not in session:
|
||||
return jsonify({'success': False, 'error': 'Unauthorized'}), 401
|
||||
|
||||
try:
|
||||
limit = request.args.get('limit', 100, type=int)
|
||||
if limit > 500:
|
||||
limit = 500
|
||||
if limit < 1:
|
||||
limit = 1
|
||||
|
||||
orders = get_printed_orders_data(limit)
|
||||
return jsonify({'success': True, 'orders': orders, 'count': len(orders)}), 200
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting printed orders: {e}")
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
|
||||
@labels_bp.route('/api/search-orders', methods=['POST'], endpoint='api_search_orders')
|
||||
def api_search_orders():
|
||||
"""Search for orders by CP code"""
|
||||
if 'user_id' not in session:
|
||||
return jsonify({'success': False, 'error': 'Unauthorized'}), 401
|
||||
|
||||
try:
|
||||
data = request.get_json()
|
||||
cp_code = data.get('cp_code', '').strip()
|
||||
|
||||
if not cp_code or len(cp_code) < 1:
|
||||
return jsonify({'success': False, 'error': 'CP code is required'}), 400
|
||||
|
||||
results = search_orders_by_cp_code(cp_code)
|
||||
return jsonify({'success': True, 'orders': results, 'count': len(results)}), 200
|
||||
except Exception as e:
|
||||
logger.error(f"Error searching orders: {e}")
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
|
||||
@labels_bp.route('/api/update-printed-status/<int:order_id>', methods=['POST'], endpoint='api_update_printed_status')
|
||||
def api_update_printed_status(order_id):
|
||||
"""Mark an order as printed"""
|
||||
if 'user_id' not in session:
|
||||
return jsonify({'success': False, 'error': 'Unauthorized'}), 401
|
||||
|
||||
try:
|
||||
data = request.get_json() or {}
|
||||
printed = data.get('printed', True)
|
||||
|
||||
success = update_order_printed_status(order_id, printed)
|
||||
if success:
|
||||
return jsonify({'success': True, 'message': 'Order status updated'}), 200
|
||||
else:
|
||||
return jsonify({'success': False, 'error': 'Failed to update order'}), 500
|
||||
except Exception as e:
|
||||
logger.error(f"Error updating order status: {e}")
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
Reference in New Issue
Block a user