diff --git a/app.py b/app.py index 29e8747..3149bd7 100644 --- a/app.py +++ b/app.py @@ -95,8 +95,8 @@ except Exception as e: sys_log.error(f"無法檢測磁碟空間: {e}") # 🚩 系統版本定義 (備份與顯示用) -# 🚩 2026-04-30 V10.36: EDM dashboard v2 feature flag -SYSTEM_VERSION = "V10.36" +# 🚩 2026-04-30 V10.37: Vendor stockout v2 feature flag +SYSTEM_VERSION = "V10.37" # ========================================== # 🔒 SQL Injection 防護函數 diff --git a/routes/vendor_routes.py b/routes/vendor_routes.py index 0c107f5..8528499 100644 --- a/routes/vendor_routes.py +++ b/routes/vendor_routes.py @@ -35,10 +35,78 @@ vendor_db = VendorDatabaseManager() # 主要頁面路由 # ========================================== + +def _get_vendor_dashboard_stats(): + """彙整廠商缺貨首頁 V2 所需的真實資料庫統計。""" + session = vendor_db.get_session() + try: + total_stockouts = session.query(VendorStockout).count() + pending_stockouts = session.query(VendorStockout).filter(or_( + VendorStockout.status == 'pending', + VendorStockout.status == None + )).count() + sent_stockouts = session.query(VendorStockout).filter(VendorStockout.status == 'sent').count() + failed_stockouts = session.query(VendorStockout).filter(VendorStockout.status == 'failed').count() + duplicate_stockouts = session.query(VendorStockout).filter(VendorStockout.is_duplicate == True).count() + distinct_vendor_count = session.query(VendorStockout.vendor_code).distinct().count() + + active_vendors = session.query(VendorList).filter(VendorList.is_active == True).count() + inactive_vendors = session.query(VendorList).filter(VendorList.is_active == False).count() + active_emails = session.query(VendorEmail).filter(VendorEmail.is_active == True).count() + + email_total = session.query(EmailSendLog).count() + email_success = session.query(EmailSendLog).filter(EmailSendLog.status == 'sent').count() + email_failed = session.query(EmailSendLog).filter(EmailSendLog.status == 'failed').count() + email_pending = session.query(EmailSendLog).filter(EmailSendLog.status == 'pending').count() + email_success_rate = round(email_success / email_total * 100, 1) if email_total else 0 + + latest_import = session.query(VendorStockout).order_by(desc(VendorStockout.created_at)).first() + latest_email = session.query(EmailSendLog).order_by(desc(EmailSendLog.created_at)).first() + latest_batch = session.query( + VendorStockout.batch_id, + func.count(VendorStockout.id).label('record_count'), + func.max(VendorStockout.created_at).label('latest_date') + ).group_by(VendorStockout.batch_id).order_by(desc('latest_date')).first() + + return { + 'total_stockouts': total_stockouts, + 'pending_stockouts': pending_stockouts, + 'sent_stockouts': sent_stockouts, + 'failed_stockouts': failed_stockouts, + 'duplicate_stockouts': duplicate_stockouts, + 'distinct_vendor_count': distinct_vendor_count, + 'active_vendors': active_vendors, + 'inactive_vendors': inactive_vendors, + 'active_emails': active_emails, + 'email_total': email_total, + 'email_success': email_success, + 'email_failed': email_failed, + 'email_pending': email_pending, + 'email_success_rate': email_success_rate, + 'latest_import_time': latest_import.created_at if latest_import else None, + 'latest_import_vendor': latest_import.vendor_name if latest_import else None, + 'latest_import_product': latest_import.product_name if latest_import else None, + 'latest_email_time': latest_email.created_at if latest_email else None, + 'latest_email_status': latest_email.status if latest_email else None, + 'latest_email_vendor_id': latest_email.vendor_id if latest_email else None, + 'latest_batch_id': latest_batch.batch_id if latest_batch else None, + 'latest_batch_count': latest_batch.record_count if latest_batch else 0, + 'latest_batch_time': latest_batch.latest_date if latest_batch else None, + } + finally: + session.close() + + @vendor_bp.route('/') def index(): """廠商缺貨系統主頁""" sys_log.info("[VendorStockout] 進入廠商缺貨系統主頁") + if request.args.get('ui') == 'v2': + return render_template( + 'vendor_stockout_index_v2.html', + active_page='vendor_stockout', + stats=_get_vendor_dashboard_stats() + ) return render_template('vendor_stockout/index.html') diff --git a/templates/vendor_stockout_index_v2.html b/templates/vendor_stockout_index_v2.html new file mode 100644 index 0000000..917f32b --- /dev/null +++ b/templates/vendor_stockout_index_v2.html @@ -0,0 +1,497 @@ +{% extends 'ewoooc_base.html' %} + +{% block title %}EwoooC 廠商缺貨{% endblock %} + +{% block extra_css %} + +{% endblock %} + +{% block ewooo_content %} +
+ 以匯入的缺貨清單、廠商聯絡資料與郵件發送紀錄為準,追蹤待處理缺貨、已發送通知與聯絡資料完整度。 +
+