From c38b5d7b4450b0b2966a98ff30434f85ba2a6e85 Mon Sep 17 00:00:00 2001 From: ske087 Date: Tue, 25 Nov 2025 00:09:19 +0200 Subject: [PATCH] Add Daily Mirror interactive dashboard with charts and pivot tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Created comprehensive dashboard with Chart.js visualizations - Added API endpoint /api/dashboard_data for aggregated data - Implemented weekly tracking for orders, production, and deliveries - Added interactive pivot table for customer × week analysis - Fixed collation issues in database joins - Includes 4 summary cards with key metrics - Charts display orders, production finished, and deliveries by week - Click-to-expand data tables for detailed view - Time range filter (4-52 weeks) - Data sources: scanfg_orders (finished), dm_orders, dm_deliveries --- py_app/app/daily_mirror.py | 171 ++- py_app/app/templates/daily_mirror.html | 1367 +++++++++++++++++------- 2 files changed, 1124 insertions(+), 414 deletions(-) diff --git a/py_app/app/daily_mirror.py b/py_app/app/daily_mirror.py index c4364bb..6cb4c2d 100644 --- a/py_app/app/daily_mirror.py +++ b/py_app/app/daily_mirror.py @@ -568,6 +568,175 @@ def api_daily_mirror_history_data(): return jsonify({'error': str(e)}), 500 +@daily_mirror_bp.route('/api/dashboard_data', methods=['GET']) +def api_dashboard_data(): + """API endpoint to get aggregated dashboard data for pivot table view""" + access_check = check_daily_mirror_api_access() + if access_check: + return access_check + + try: + print(f"DEBUG: dashboard_data API called") + from datetime import datetime, timedelta + + # Get date range parameters + weeks_back = int(request.args.get('weeks_back', 12)) + end_date = datetime.now() + start_date = end_date - timedelta(weeks=weeks_back) + + dm_db = DailyMirrorDatabase() + if not dm_db.connect(): + return jsonify({'error': 'Database connection failed'}), 500 + + cursor = dm_db.connection.cursor() + + # 1. Get finished orders from scanfg_orders (production finished) + cursor.execute(""" + SELECT + DATE_FORMAT(date, '%%Y%%u') as week_number, + DATE_FORMAT(date, '%%Y-W%%u') as week_display, + COUNT(*) as finished_count, + SUM(approved_quantity) as approved_qty, + SUM(rejected_quantity) as rejected_qty + FROM scanfg_orders + WHERE date >= %s AND date <= %s + GROUP BY week_number, week_display + ORDER BY week_number + """, (start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d'))) + finished_orders_raw = cursor.fetchall() + finished_orders = [ + { + 'week_number': row[0], + 'week_display': row[1], + 'finished_count': row[2], + 'approved_qty': row[3], + 'rejected_qty': row[4] + } + for row in finished_orders_raw + ] + + # 2. Get customer orders from dm_orders by customer and week + cursor.execute(""" + SELECT + c.customer_name, + DATE_FORMAT(o.order_date, '%%Y%%u') as week_number, + DATE_FORMAT(o.order_date, '%%Y-W%%u') as week_display, + COUNT(*) as order_count, + SUM(o.quantity_requested) as total_quantity, + SUM(CASE WHEN o.order_status = 'OPEN' THEN o.quantity_requested ELSE 0 END) as open_quantity, + SUM(CASE WHEN o.order_status = 'COMPLETED' THEN o.quantity_requested ELSE 0 END) as completed_quantity + FROM dm_orders o + LEFT JOIN dm_customers c ON o.customer_code COLLATE utf8mb4_unicode_ci = c.customer_code COLLATE utf8mb4_unicode_ci + WHERE o.order_date >= %s AND o.order_date <= %s + GROUP BY c.customer_name, week_number, week_display + ORDER BY c.customer_name, week_number + """, (start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d'))) + customer_orders_raw = cursor.fetchall() + customer_orders = [ + { + 'customer_name': row[0], + 'week_number': row[1], + 'week_display': row[2], + 'order_count': row[3], + 'total_quantity': row[4], + 'open_quantity': row[5], + 'completed_quantity': row[6] + } + for row in customer_orders_raw + ] + + # 3. Get deliveries from dm_deliveries by customer and week + cursor.execute(""" + SELECT + c.customer_name, + DATE_FORMAT(d.delivery_date, '%%Y%%u') as week_number, + DATE_FORMAT(d.delivery_date, '%%Y-W%%u') as week_display, + COUNT(*) as delivery_count, + SUM(d.quantity_delivered) as total_delivered + FROM dm_deliveries d + LEFT JOIN dm_customers c ON d.customer_code COLLATE utf8mb4_unicode_ci = c.customer_code COLLATE utf8mb4_unicode_ci + WHERE d.delivery_date >= %s AND d.delivery_date <= %s + GROUP BY c.customer_name, week_number, week_display + ORDER BY c.customer_name, week_number + """, (start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d'))) + deliveries_raw = cursor.fetchall() + deliveries = [ + { + 'customer_name': row[0], + 'week_number': row[1], + 'week_display': row[2], + 'delivery_count': row[3], + 'total_delivered': row[4] + } + for row in deliveries_raw + ] + + # 4. Get summary metrics + cursor.execute(""" + SELECT + COUNT(*) as total_orders, + SUM(quantity_requested) as total_quantity, + COUNT(DISTINCT customer_code) as unique_customers + FROM dm_orders + WHERE order_date >= %s AND order_date <= %s + """, (start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d'))) + order_summary_row = cursor.fetchone() + + cursor.execute(""" + SELECT + COUNT(*) as total_finished, + SUM(approved_quantity) as total_approved, + SUM(rejected_quantity) as total_rejected + FROM scanfg_orders + WHERE date >= %s AND date <= %s + """, (start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d'))) + production_summary_row = cursor.fetchone() + + cursor.execute(""" + SELECT + COUNT(*) as total_deliveries, + SUM(quantity_delivered) as total_delivered + FROM dm_deliveries + WHERE delivery_date >= %s AND delivery_date <= %s + """, (start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d'))) + delivery_summary_row = cursor.fetchone() + + dm_db.disconnect() + + print(f"DEBUG: Data aggregation successful. Orders: {len(customer_orders)}, Production: {len(finished_orders)}, Deliveries: {len(deliveries)}") + + # Build response + response_data = { + 'date_range': { + 'start': start_date.strftime('%Y-%m-%d'), + 'end': end_date.strftime('%Y-%m-%d'), + 'weeks_back': weeks_back + }, + 'summary': { + 'total_orders': order_summary_row[0] or 0, + 'total_quantity': int(order_summary_row[1] or 0), + 'unique_customers': order_summary_row[2] or 0, + 'total_finished': production_summary_row[0] or 0, + 'total_approved': int(production_summary_row[1] or 0), + 'total_rejected': int(production_summary_row[2] or 0), + 'total_deliveries': delivery_summary_row[0] or 0, + 'total_delivered': int(delivery_summary_row[1] or 0) + }, + 'finished_orders_by_week': finished_orders, + 'customer_orders_by_week': customer_orders, + 'deliveries_by_week': deliveries + } + + print(f"DEBUG: Returning response data successfully") + return jsonify(response_data) + + except Exception as e: + print(f"ERROR getting dashboard data: {e}") + import traceback + traceback.print_exc() + return jsonify({'error': str(e)}), 500 + + # ============================================= # TUNE DATABASE ROUTES # ============================================= @@ -1174,4 +1343,4 @@ def clear_delivery(): except Exception as e: print(f"Error clearing delivery records: {e}") - return jsonify({'error': str(e)}), 500 \ No newline at end of file + return jsonify({'error': str(e)}), 500 diff --git a/py_app/app/templates/daily_mirror.html b/py_app/app/templates/daily_mirror.html index aa1bd7d..89009cc 100644 --- a/py_app/app/templates/daily_mirror.html +++ b/py_app/app/templates/daily_mirror.html @@ -1,447 +1,988 @@ {% extends "base.html" %} -{% block title %}Daily Mirror - Quality Recticel{% endblock %} - -{% block content %} -
- -
-
-
-
-

📈 Daily Mirror

-

Generate comprehensive daily production reports

-
- -
-
-
- - -
-
-
-
-
- Select Report Date -
-
-
-
-
- - -
-
- -
-
- -
-
-
-
-
-
- - - - - - - - - -
+{% block title %}Daily Mirror Dashboard - Quality Recticel{% endblock %} +{% block head %} + + +{% endblock %} + +{% block content %} +
+ +
+
+
+

Daily Mirror Dashboard

+

Comprehensive production, orders, and delivery analytics

+
+
+ + History + + + Back + +
+
+
+ + +
+
Time Range Filter
+
+
+ + +
+
+ +
+
+ Loading... +
+
+
+ + +
+
+
+ +
Customer Orders
+
-
+
- units ordered
+
+
+
+
+ +
Production Finished
+
-
+
- approved
+
+
+
+
+ +
Deliveries
+
-
+
- units delivered
+
+
+
+
+ +
Active Customers
+
-
+
unique customers
+
+
+
+ + +
+
+

Customer Orders by Week

+ +
+ +
+ + + + + + + + + + + + + + +
WeekCustomerOrdersTotal QuantityOpenCompleted
No data available
+
+
+ + +
+
+

Production Finished by Week

+ +
+ +
+ + + + + + + + + + + + + +
WeekFinished OrdersApproved QuantityRejected QuantityQuality Rate
No data available
+
+
+ + +
+
+

Deliveries by Week

+ +
+ +
+ + + + + + + + + + + + +
WeekCustomerDelivery CountTotal Delivered
No data available
+
+
+ + +
+
+

Customer Orders Pivot Table

+
+ +
+
+
+ + + + + + + +
Customer
Loading...
+
+
+ + + +
-{% endblock %} \ No newline at end of file +{% endblock %}