From 15b3bae9cb33fe4947c5b213f2b15db91183c9aa Mon Sep 17 00:00:00 2001 From: OoO Date: Fri, 1 May 2026 00:21:26 +0800 Subject: [PATCH] =?UTF-8?q?feat(frontend):=20=E6=96=B0=E5=A2=9E=E5=BB=A0?= =?UTF-8?q?=E5=95=86=E7=BC=BA=E8=B2=A8=E5=8C=AF=E5=85=A5=20V2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CONSTITUTION.md | 2 +- app.py | 4 +- routes/vendor_routes.py | 33 +- templates/vendor_stockout_import_v2.html | 574 +++++++++++++++++++++++ templates/vendor_stockout_index_v2.html | 4 +- templates/vendor_stockout_list_v2.html | 2 +- tests/test_frontend_v2_assets.py | 15 + 7 files changed, 606 insertions(+), 28 deletions(-) create mode 100644 templates/vendor_stockout_import_v2.html diff --git a/CONSTITUTION.md b/CONSTITUTION.md index 59695e2..65e97b3 100644 --- a/CONSTITUTION.md +++ b/CONSTITUTION.md @@ -2,7 +2,7 @@ > 本文件定義專案開發的核心準則與不可違反的規範 > **建立日期**: 2026-01-12 -> **當前版本**: V10.38 (Vendor stockout list v2 feature flag) +> **當前版本**: V10.39 (Vendor stockout import v2 feature flag) > **最後更新**: 2026-05-01 --- diff --git a/app.py b/app.py index 2b2a944..a5241c9 100644 --- a/app.py +++ b/app.py @@ -95,8 +95,8 @@ except Exception as e: sys_log.error(f"無法檢測磁碟空間: {e}") # 🚩 系統版本定義 (備份與顯示用) -# 🚩 2026-05-01 V10.38: Vendor stockout list v2 feature flag -SYSTEM_VERSION = "V10.38" +# 🚩 2026-05-01 V10.39: Vendor stockout import v2 feature flag +SYSTEM_VERSION = "V10.39" # ========================================== # 🔒 SQL Injection 防護函數 diff --git a/routes/vendor_routes.py b/routes/vendor_routes.py index cc56f5c..88f3353 100644 --- a/routes/vendor_routes.py +++ b/routes/vendor_routes.py @@ -211,6 +211,11 @@ def index(): def import_page(): """Excel 匯入頁面""" sys_log.info("[VendorStockout] 進入匯入頁面") + if request.args.get('ui') == 'v2': + return render_template( + 'vendor_stockout_import_v2.html', + active_page='vendor_stockout' + ) return render_template('vendor_stockout/import.html') @@ -428,28 +433,12 @@ def api_import_excel(): def api_import_template(): """下載 Excel 匯入範本(使用實際欄位名稱)""" try: - # 建立範本 DataFrame(使用實際的欄位名稱) - template_data = { - '當前日期': ['2026-01-12'], - '處別': ['範例處別'], - '科別': ['範例科別'], - 'PM姓名': ['王小明'], - '區ID': ['A01'], - '區名稱': ['範例區域'], - '商品ID': ['123456789'], - '商品名稱': ['範例商品名稱'], - '單品/組合商品': ['單品'], - '借採轉': ['否'], - '來源供應商編號': ['V001'], - '來源供應商名稱': ['範例供應商股份有限公司'], - '商品可賣量': [50], - '缺貨日期': ['2026-01-10'], - '缺貨天數': [2], - '缺貨商品前30天業績': [150000], - '最近30天銷售量': [300], - '庫存水位': ['低'] - } - df = pd.DataFrame(template_data) + template_columns = [ + '當前日期', '處別', '科別', 'PM姓名', '區ID', '區名稱', '商品ID', '商品名稱', + '單品/組合商品', '借採轉', '來源供應商編號', '來源供應商名稱', '商品可賣量', + '缺貨日期', '缺貨天數', '缺貨商品前30天業績', '最近30天銷售量', '庫存水位' + ] + df = pd.DataFrame(columns=template_columns) # 輸出到記憶體 output = io.BytesIO() diff --git a/templates/vendor_stockout_import_v2.html b/templates/vendor_stockout_import_v2.html new file mode 100644 index 0000000..96caf9c --- /dev/null +++ b/templates/vendor_stockout_import_v2.html @@ -0,0 +1,574 @@ +{% extends 'ewoooc_base.html' %} + +{% block title %}EwoooC 缺貨匯入{% endblock %} + +{% block extra_css %} + +{% endblock %} + +{% block ewooo_content %} +
+
+
+
+ + STOCKOUT IMPORT +
+

Excel 匯入

+

+ 上傳正式缺貨 Excel 後,系統會使用既有匯入 API 寫入 vendor_stockout,完成後直接回傳批次編號與成功、重複、失敗筆數。 +

+ +
+ +
+ +
+ + + +
+ +
+
+
+
已選擇檔案
+
+
+
+ +
+
+ +
+
匯入中
+
+
+
+
+ +
+
匯入結果
+
+
+
0
+
總筆數
+
+
+
0
+
成功匯入
+
+
+
0
+
重複項目
+
+
+
0
+
失敗
+
+
+
批次編號
+
+ + + 查看缺貨清單 + + +
+
+ +
+
匯入失敗
+
+
+
+{% endblock %} + +{% block extra_js %} + +{% endblock %} diff --git a/templates/vendor_stockout_index_v2.html b/templates/vendor_stockout_index_v2.html index 226eea1..f23dfe3 100644 --- a/templates/vendor_stockout_index_v2.html +++ b/templates/vendor_stockout_index_v2.html @@ -341,7 +341,7 @@

- + 匯入 Excel @@ -408,7 +408,7 @@ 工作入口
- + Excel 匯入 diff --git a/templates/vendor_stockout_list_v2.html b/templates/vendor_stockout_list_v2.html index 0f1cb01..277b993 100644 --- a/templates/vendor_stockout_list_v2.html +++ b/templates/vendor_stockout_list_v2.html @@ -334,7 +334,7 @@ 回總覽 - + 匯入 Excel diff --git a/tests/test_frontend_v2_assets.py b/tests/test_frontend_v2_assets.py index d8edfa5..517fb79 100644 --- a/tests/test_frontend_v2_assets.py +++ b/tests/test_frontend_v2_assets.py @@ -99,3 +99,18 @@ def test_vendor_stockout_list_v2_is_feature_flagged_and_uses_real_stockout_rows( assert "record.vendor_name" in template assert "mock" not in template.lower() assert "假" not in template + + +def test_vendor_stockout_import_v2_is_feature_flagged_and_does_not_ship_sample_rows(): + route_source = (ROOT / "routes/vendor_routes.py").read_text(encoding="utf-8") + template = (ROOT / "templates/vendor_stockout_import_v2.html").read_text(encoding="utf-8") + template_function = route_source.split("def api_import_template():", 1)[1].split("@vendor_bp.route('/api/stockout/list'", 1)[0] + + assert "vendor_stockout_import_v2.html" in route_source + assert "template_columns = [" in template_function + assert "pd.DataFrame(columns=template_columns)" in template_function + assert "fetchWithCSRF('/vendor-stockout/api/import/excel'" in template + assert "vendor_stockout" in template + assert "範例" not in template_function + assert "mock" not in template.lower() + assert "假" not in template