diff --git a/config.py b/config.py index f3d6453..100635a 100644 --- a/config.py +++ b/config.py @@ -320,7 +320,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '') # ========================================== # 系統版本與路徑 # ========================================== -SYSTEM_VERSION = "V10.111" +SYSTEM_VERSION = "V10.112" LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log') public_url = PUBLIC_URL # 用於模板顯示 diff --git a/routes/sales_routes.py b/routes/sales_routes.py index fcff7d0..627291d 100644 --- a/routes/sales_routes.py +++ b/routes/sales_routes.py @@ -839,6 +839,19 @@ def sales_analysis(): # V-New: 按需載入 - 如果沒有任何篩選條件,顯示引導頁面 if not data_range_param and not start_date and not end_date: sys_log.info("[Sales Analysis] 👋 首次進入頁面,等待用戶選擇篩選條件") + preview_cache_key = "sales_analysis:page_context:" + _sales_analysis_args_fingerprint( + table_name, + 'preview', + SYSTEM_VERSION, + ) + cached_preview_context = ( + _get_sales_page_context_cache(preview_cache_key) + or _get_sales_shared_page_context_cache(preview_cache_key) + ) + if cached_preview_context: + _set_sales_page_context_cache(preview_cache_key, cached_preview_context) + return render_template('sales_analysis.html', **cached_preview_context) + preview_options = _preview_sales_filter_options(db.engine, table_name) preview_categories = preview_options['categories'] preview_brands = preview_options['brands'] @@ -851,42 +864,61 @@ def sales_analysis(): selected_metric = request.args.get('metric', 'amount') # 建立空的數據結構 empty_data = {'labels': [], 'chart_values': [], 'values': [], 'metric_label': ''} - return render_template('sales_analysis.html', - no_filter=True, - table_name=table_name, - selected_metric=selected_metric, - total_records=0, - items=[], - kpi={'revenue': 0, 'qty': 0, 'count': 0, 'cost': 0, 'gross_margin': 0, 'gross_margin_rate': 0, 'avg_price': 0}, - insights={}, - abc_stats={}, - vendor_stats=[], - seasonality_data={'datasets': [], 'yLabels': [], 'xLabels': []}, - bar_data=empty_data, - cat_data=empty_data, - category_data=empty_data, - price_dist_data=empty_data, - scatter_data=[], - bcg_data=[], - dow_data=empty_data, - hourly_data=empty_data, - monthly_data=empty_data, - weekly_data=empty_data, - heatmap_data=[], - treemap_data=[], - cols={'name': True, 'amount': True, 'qty': True, 'cat': True, 'date': True, - 'cost': True, 'profit': True, 'vendor': True, 'brand': True, - 'return_qty': True, 'pid': True}, - all_categories=preview_categories, all_brands=preview_brands, all_vendors=preview_vendors, - all_activities=preview_activities, all_payments=preview_payments, all_months=preview_months, - selected_category='all', selected_brand='all', selected_vendor='all', - selected_activity='all', selected_payment='all', selected_dow='all', - selected_hour='all', selected_month='all', - keyword='', min_price='', max_price='', min_margin='', max_margin='', - data_range_months=0, start_date='', end_date='', - db_data_range=db_data_range, - active_page='sales', - marketing_data=None) + preview_context = { + 'no_filter': True, + 'table_name': table_name, + 'selected_metric': selected_metric, + 'total_records': 0, + 'items': [], + 'kpi': {'revenue': 0, 'qty': 0, 'count': 0, 'cost': 0, 'gross_margin': 0, 'gross_margin_rate': 0, 'avg_price': 0}, + 'insights': {}, + 'abc_stats': {}, + 'vendor_stats': [], + 'seasonality_data': {'datasets': [], 'yLabels': [], 'xLabels': []}, + 'bar_data': empty_data, + 'cat_data': empty_data, + 'category_data': empty_data, + 'price_dist_data': empty_data, + 'scatter_data': [], + 'bcg_data': [], + 'dow_data': empty_data, + 'hourly_data': empty_data, + 'monthly_data': empty_data, + 'weekly_data': empty_data, + 'heatmap_data': [], + 'treemap_data': [], + 'cols': {'name': True, 'amount': True, 'qty': True, 'cat': True, 'date': True, + 'cost': True, 'profit': True, 'vendor': True, 'brand': True, + 'return_qty': True, 'pid': True}, + 'all_categories': preview_categories, + 'all_brands': preview_brands, + 'all_vendors': preview_vendors, + 'all_activities': preview_activities, + 'all_payments': preview_payments, + 'all_months': preview_months, + 'selected_category': 'all', + 'selected_brand': 'all', + 'selected_vendor': 'all', + 'selected_activity': 'all', + 'selected_payment': 'all', + 'selected_dow': 'all', + 'selected_hour': 'all', + 'selected_month': 'all', + 'keyword': '', + 'min_price': '', + 'max_price': '', + 'min_margin': '', + 'max_margin': '', + 'data_range_months': 0, + 'start_date': '', + 'end_date': '', + 'db_data_range': db_data_range, + 'active_page': 'sales', + 'marketing_data': None, + } + _set_sales_page_context_cache(preview_cache_key, preview_context) + _set_sales_shared_page_context_cache(preview_cache_key, preview_context) + return render_template('sales_analysis.html', **preview_context) # 解析 data_range_months(有篩選時才處理) data_range_months = int(data_range_param or '0')