Some checks failed
CD Pipeline / deploy (push) Failing after 59s
- 建立 Gitea Actions CD pipeline (.gitea/workflows/cd.yaml) - 部署模式: rsync Python 檔案至 188 → docker restart (volume mount) - Dockerfile/requirements 變動時自動重建 Docker image - 部署通知: Telegram (開始/成功/失敗) - 健康檢查: https://mo.wooo.work/health (最多 5 次重試) - 同步最新 CLAUDE.md / ADR-008 / memory (2026-04-19) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
169 lines
5.4 KiB
Python
169 lines
5.4 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
測試完整匯入流程
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
import pandas as pd
|
|
import numpy as np
|
|
from datetime import date, datetime
|
|
from database.vendor_manager import VendorDatabaseManager
|
|
from database.vendor_models import VendorStockout
|
|
|
|
# 讀取 Excel
|
|
excel_path = '/Users/ogt/Downloads/缺貨測試.xlsx'
|
|
df = pd.read_excel(excel_path)
|
|
|
|
print("=" * 80)
|
|
print("測試完整匯入流程")
|
|
print("=" * 80)
|
|
|
|
# 檢查是否有當前日期欄位
|
|
has_date_column = '當前日期' in df.columns
|
|
print(f"\n是否有當前日期欄位: {has_date_column}")
|
|
|
|
# 處理第一行
|
|
idx = 0
|
|
row = df.iloc[idx]
|
|
|
|
print(f"\n處理第 {idx+1} 行")
|
|
print("-" * 80)
|
|
|
|
# 日期轉換
|
|
row_import_date = date.today()
|
|
if has_date_column:
|
|
date_value = row.get('當前日期')
|
|
print(f"當前日期原始值: {date_value}, 類型: {type(date_value).__name__}")
|
|
|
|
if pd.notna(date_value):
|
|
print(f" pd.notna: True")
|
|
if isinstance(date_value, (int, float, np.integer, np.floating)):
|
|
print(f" 是數字類型 (包括 numpy)")
|
|
parsed_date = pd.to_datetime(date_value, unit='D', origin='1899-12-30', errors='coerce')
|
|
print(f" parsed_date: {parsed_date}")
|
|
if pd.notna(parsed_date):
|
|
row_import_date = parsed_date.date()
|
|
print(f" ✅ 轉換成功: {row_import_date}")
|
|
|
|
# 缺貨日期轉換
|
|
stockout_date_value = row.get('缺貨日期')
|
|
stockout_date_obj = None
|
|
print(f"\n缺貨日期原始值: {stockout_date_value}, 類型: {type(stockout_date_value).__name__}")
|
|
|
|
if pd.notna(stockout_date_value):
|
|
print(f" pd.notna: True")
|
|
if isinstance(stockout_date_value, (int, float, np.integer, np.floating)):
|
|
print(f" 是數字類型 (包括 numpy)")
|
|
stockout_parsed = pd.to_datetime(stockout_date_value, unit='D', origin='1899-12-30', errors='coerce')
|
|
print(f" stockout_parsed: {stockout_parsed}")
|
|
if pd.notna(stockout_parsed):
|
|
stockout_date_obj = stockout_parsed.date()
|
|
print(f" ✅ 轉換成功: {stockout_date_obj}")
|
|
|
|
# 建立 record
|
|
print("\n建立 record:")
|
|
print("-" * 80)
|
|
|
|
record = {
|
|
'import_date': row_import_date,
|
|
'department': row.get('處別'),
|
|
'section': row.get('科別'),
|
|
'pm_name': row.get('PM姓名'),
|
|
'zone_id': row.get('區ID'),
|
|
'zone_name': row.get('區名稱'),
|
|
'product_code': str(row.get('商品ID', '')).strip(),
|
|
'product_name': str(row.get('商品名稱', '')).strip(),
|
|
'product_spec': row.get('單品/組合商品'),
|
|
'borrow_transfer': row.get('借採轉'),
|
|
'sale_price': None,
|
|
'cost_price': None,
|
|
'vendor_code': str(row.get('來源供應商編號', '')).strip(),
|
|
'vendor_name': str(row.get('來源供應商名稱', '')).strip(),
|
|
'current_stock': row.get('商品可賣量'),
|
|
'stockout_date': stockout_date_obj,
|
|
'stockout_days': row.get('缺貨天數'),
|
|
'monthly_sales_amount': row.get('缺貨商品前30天業績'),
|
|
'monthly_sales_qty': row.get('最近30天銷售量'),
|
|
'daily_avg_sales': None,
|
|
'safe_stock_days': row.get('庫存水位'),
|
|
'notes': None
|
|
}
|
|
|
|
for key, value in record.items():
|
|
print(f" {key}: {value}")
|
|
|
|
# 寫入資料庫
|
|
print("\n" + "=" * 80)
|
|
print("寫入資料庫")
|
|
print("=" * 80)
|
|
|
|
db = VendorDatabaseManager()
|
|
session = db.get_session()
|
|
|
|
try:
|
|
# 生成批次ID
|
|
batch_id = datetime.now().strftime('%Y%m%d_%H%M%S')
|
|
|
|
stockout_item = VendorStockout(
|
|
batch_id=batch_id,
|
|
import_date=record['import_date'],
|
|
import_time=datetime.now(),
|
|
department=record['department'],
|
|
section=record['section'],
|
|
pm_name=record['pm_name'],
|
|
zone_id=record['zone_id'],
|
|
zone_name=record['zone_name'],
|
|
product_code=record['product_code'],
|
|
product_name=record['product_name'],
|
|
product_spec=record['product_spec'],
|
|
borrow_transfer=record['borrow_transfer'],
|
|
sale_price=record['sale_price'],
|
|
cost_price=record['cost_price'],
|
|
vendor_code=record['vendor_code'],
|
|
vendor_name=record['vendor_name'],
|
|
monthly_sales_qty=record['monthly_sales_qty'],
|
|
monthly_sales_amount=record['monthly_sales_amount'],
|
|
daily_avg_sales=record['daily_avg_sales'],
|
|
current_stock=record['current_stock'],
|
|
stockout_date=record['stockout_date'],
|
|
stockout_days=record['stockout_days'],
|
|
safe_stock_days=record['safe_stock_days'],
|
|
notes=record['notes'],
|
|
status='pending'
|
|
)
|
|
|
|
session.add(stockout_item)
|
|
session.commit()
|
|
|
|
print(f"✅ 寫入成功")
|
|
|
|
# 刷新 session
|
|
session.expire_all()
|
|
|
|
# 讀回資料驗證
|
|
print("\n讀回資料驗證:")
|
|
print("-" * 80)
|
|
saved = session.query(VendorStockout).filter_by(product_code=record['product_code']).first()
|
|
|
|
if saved:
|
|
print(f" 當前日期: {saved.import_date}")
|
|
print(f" 區ID: {saved.zone_id}")
|
|
print(f" 區名稱: {saved.zone_name}")
|
|
print(f" 借採轉: {saved.borrow_transfer}")
|
|
print(f" 缺貨日期: {saved.stockout_date}")
|
|
print(f" 缺貨天數: {saved.stockout_days}")
|
|
print(f" 商品可賣量: {saved.current_stock}")
|
|
print(f" 庫存水位: {saved.safe_stock_days}")
|
|
|
|
except Exception as e:
|
|
session.rollback()
|
|
print(f"❌ 寫入失敗: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
finally:
|
|
session.close()
|