""" Quality Module Routes """ from flask import Blueprint, render_template, session, redirect, url_for, request, jsonify, flash from app.modules.quality.quality import ( ensure_scanfg_orders_table, save_fg_scan, get_latest_scans, get_fg_report, get_daily_statistics, get_cp_statistics ) import logging logger = logging.getLogger(__name__) quality_bp = Blueprint('quality', __name__, url_prefix='/quality') @quality_bp.route('/', methods=['GET']) def quality_index(): """Quality module main page""" if 'user_id' not in session: return redirect(url_for('main.login')) return render_template('modules/quality/index.html') @quality_bp.route('/reports', methods=['GET']) def quality_reports(): """Quality reports page - displays FG scan reports""" if 'user_id' not in session: return redirect(url_for('main.login')) # Ensure scanfg_orders table exists ensure_scanfg_orders_table() return render_template('modules/quality/fg_reports.html') @quality_bp.route('/fg_scan', methods=['GET', 'POST']) def fg_scan(): """Finish goods scan page - POST saves scan data, GET displays form and latest scans""" if 'user_id' not in session: return redirect(url_for('main.login')) # Ensure scanfg_orders table exists ensure_scanfg_orders_table() if request.method == 'POST': # Handle form submission operator_code = request.form.get('operator_code') cp_code = request.form.get('cp_code') oc1_code = request.form.get('oc1_code') oc2_code = request.form.get('oc2_code') defect_code = request.form.get('defect_code') date = request.form.get('date') time = request.form.get('time') try: # Save the scan using business logic function success, approved_count, rejected_count = save_fg_scan( operator_code, cp_code, oc1_code, oc2_code, defect_code, date, time ) # Flash appropriate message based on defect code if int(defect_code) == 0 or defect_code == '000': flash(f'✅ APPROVED scan recorded for {cp_code}. Total approved: {approved_count}') else: flash(f'❌ REJECTED scan recorded for {cp_code} (defect: {defect_code}). Total rejected: {rejected_count}') except Exception as e: logger.error(f"Error saving finish goods scan data: {e}") flash(f"Error saving scan data: {str(e)}", 'error') # Check if this is an AJAX request (for scan-to-boxes feature) if request.headers.get('X-Requested-With') == 'XMLHttpRequest' or request.accept_mimetypes.best == 'application/json': # For AJAX requests, return JSON response without redirect return jsonify({'success': True, 'message': 'Scan recorded successfully'}) # For normal form submissions, redirect to prevent form resubmission (POST-Redirect-GET pattern) return redirect(url_for('quality.fg_scan')) # GET request - Fetch and display latest scans try: scan_groups = get_latest_scans(limit=25) except Exception as e: logger.error(f"Error fetching latest scans: {e}") flash(f"Error fetching scan data: {str(e)}", 'error') scan_groups = [] return render_template('modules/quality/fg_scan.html', scan_groups=scan_groups) # API Routes for AJAX requests @quality_bp.route('/api/fg_report', methods=['POST']) def api_fg_report(): """ API endpoint for generating FG reports via AJAX Expected JSON body: { 'report_type': 'daily|select-day|date-range|5-day|defects-today|defects-date|defects-range|defects-5day|all', 'filter_date': 'YYYY-MM-DD' (optional, for select-day/defects-date), 'start_date': 'YYYY-MM-DD' (optional, for date-range/defects-range), 'end_date': 'YYYY-MM-DD' (optional, for date-range/defects-range) } """ if 'user_id' not in session: return jsonify({'success': False, 'message': 'Unauthorized'}), 401 try: data = request.get_json() report_type = data.get('report_type') filter_date = data.get('filter_date') start_date = data.get('start_date') end_date = data.get('end_date') # Validate report type valid_types = ['daily', 'select-day', 'date-range', '5-day', 'defects-today', 'defects-date', 'defects-range', 'defects-5day', 'all'] if report_type not in valid_types: return jsonify({'success': False, 'message': 'Invalid report type'}), 400 # Generate report result = get_fg_report(report_type, filter_date, start_date, end_date) return jsonify(result) except Exception as e: logger.error(f"Error in API fg_report: {e}") return jsonify({ 'success': False, 'message': f'Error processing report: {str(e)}' }), 500 @quality_bp.route('/api/daily_stats', methods=['GET']) def api_daily_stats(): """API endpoint for today's statistics""" if 'user_id' not in session: return jsonify({'success': False, 'message': 'Unauthorized'}), 401 try: stats = get_daily_statistics() return jsonify({ 'success': True, 'data': stats }) except Exception as e: logger.error(f"Error in API daily_stats: {e}") return jsonify({ 'success': False, 'message': f'Error fetching statistics: {str(e)}' }), 500 @quality_bp.route('/api/cp_stats/', methods=['GET']) def api_cp_stats(cp_code): """API endpoint for CP code statistics""" if 'user_id' not in session: return jsonify({'success': False, 'message': 'Unauthorized'}), 401 try: stats = get_cp_statistics(cp_code) return jsonify({ 'success': True, 'data': stats }) except Exception as e: logger.error(f"Error in API cp_stats: {e}") return jsonify({ 'success': False, 'message': f'Error fetching CP statistics: {str(e)}' }), 500