Add Daily Mirror interactive dashboard with charts and pivot tables
- 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
This commit is contained in:
@@ -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
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user