refactor: unify special suppliers processing into a single intelligent flow
This commit is contained in:
parent
708402c7fb
commit
26835e265a
@ -84,15 +84,35 @@ class OrderService:
|
|||||||
return self.excel_processor.process_specific_file(file_path, progress_cb=progress_cb)
|
return self.excel_processor.process_specific_file(file_path, progress_cb=progress_cb)
|
||||||
|
|
||||||
def _check_special_preprocess(self, file_path: str) -> Optional[str]:
|
def _check_special_preprocess(self, file_path: str) -> Optional[str]:
|
||||||
"""检查并执行特殊的预处理"""
|
"""检查并执行特殊的预处理(支持杨碧月、烟草公司、蓉城易购)"""
|
||||||
try:
|
try:
|
||||||
from app.core.utils.file_utils import smart_read_excel
|
from app.core.utils.file_utils import smart_read_excel
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
import re
|
||||||
|
|
||||||
# 仅读取前几行进行识别
|
# 仅读取前 50 行进行智能识别
|
||||||
df_head = smart_read_excel(file_path, nrows=50)
|
df_head = smart_read_excel(file_path, nrows=50)
|
||||||
|
df_str = df_head.astype(str)
|
||||||
|
|
||||||
# 1. 检查“杨碧月”
|
# 1. 识别:烟草公司 (Tobacco)
|
||||||
|
# 特征:通常包含“烟草”、“卷烟”等关键字,且有特定的表头结构
|
||||||
|
is_tobacco = df_str.apply(lambda x: x.str.contains('烟草|卷烟|营销中心')).any().any()
|
||||||
|
if is_tobacco:
|
||||||
|
logger.info("识别到烟草公司订单,执行专用预处理...")
|
||||||
|
from .tobacco_service import TobaccoService
|
||||||
|
tobacco_svc = TobaccoService(self.config)
|
||||||
|
return tobacco_svc.process_tobacco_order(file_path)
|
||||||
|
|
||||||
|
# 2. 识别:蓉城易购 (Rongcheng Yigou)
|
||||||
|
# 特征:通常文件名包含“订单”或内容包含“订购单位”等
|
||||||
|
is_rongcheng = df_str.apply(lambda x: x.str.contains('蓉城易购|订购单位|出库小计')).any().any()
|
||||||
|
if is_rongcheng:
|
||||||
|
logger.info("识别到蓉城易购订单,执行专用预处理...")
|
||||||
|
from .special_suppliers_service import SpecialSuppliersService
|
||||||
|
special_svc = SpecialSuppliersService(self.config)
|
||||||
|
return special_svc.process_rongcheng_yigou(file_path)
|
||||||
|
|
||||||
|
# 3. 识别:杨碧月 (Yang Biyue)
|
||||||
handler_col = None
|
handler_col = None
|
||||||
for col in df_head.columns:
|
for col in df_head.columns:
|
||||||
if '经手人' in str(col):
|
if '经手人' in str(col):
|
||||||
@ -100,38 +120,27 @@ class OrderService:
|
|||||||
break
|
break
|
||||||
|
|
||||||
if handler_col is not None and df_head[handler_col].astype(str).str.contains('杨碧月').any():
|
if handler_col is not None and df_head[handler_col].astype(str).str.contains('杨碧月').any():
|
||||||
logger.info("识别到杨碧月订单,执行预处理...")
|
logger.info("识别到杨碧月订单,执行通用预处理...")
|
||||||
# 重新读取完整数据
|
|
||||||
df = smart_read_excel(file_path)
|
df = smart_read_excel(file_path)
|
||||||
column_map = {
|
column_map = {
|
||||||
'商品条码': '商品条码', '商品名称': '商品名称', '规格': '规格',
|
'商品条码': '商品条码', '商品名称': '商品名称', '规格': '规格',
|
||||||
'单位': '单位', '数量': '数量', '单价': '单价', '金额': '金额'
|
'单位': '单位', '数量': '数量', '单价': '单价', '金额': '金额'
|
||||||
}
|
}
|
||||||
found_cols = {}
|
found_cols = {}
|
||||||
# 优先级排序,确保更精确的匹配
|
|
||||||
for target_zh, std_name in column_map.items():
|
for target_zh, std_name in column_map.items():
|
||||||
for col in df.columns:
|
for col in df.columns:
|
||||||
col_str = str(col)
|
col_str = str(col)
|
||||||
if target_zh == col_str: # 精确匹配优先
|
if target_zh == col_str: found_cols[col] = std_name; break
|
||||||
found_cols[col] = std_name
|
|
||||||
break
|
|
||||||
if std_name not in found_cols.values():
|
if std_name not in found_cols.values():
|
||||||
for col in df.columns:
|
for col in df.columns:
|
||||||
col_str = str(col)
|
if target_zh in str(col): found_cols[col] = std_name; break
|
||||||
if target_zh in col_str: # 模糊匹配
|
|
||||||
found_cols[col] = std_name
|
|
||||||
break
|
|
||||||
|
|
||||||
if len(found_cols) >= 4:
|
if len(found_cols) >= 4:
|
||||||
df_clean = df[list(found_cols.keys())].copy()
|
df_clean = df[list(found_cols.keys())].copy()
|
||||||
df_clean = df_clean.rename(columns=found_cols)
|
df_clean = df_clean.rename(columns=found_cols)
|
||||||
|
|
||||||
# 确保数量和价格是数值
|
|
||||||
# 这里的列名已经改回中文了
|
|
||||||
for c in ['数量', '单价', '金额']:
|
for c in ['数量', '单价', '金额']:
|
||||||
if c in df_clean.columns:
|
if c in df_clean.columns:
|
||||||
df_clean[c] = pd.to_numeric(df_clean[c], errors='coerce').fillna(0)
|
df_clean[c] = pd.to_numeric(df_clean[c], errors='coerce').fillna(0)
|
||||||
|
|
||||||
df_clean = df_clean.dropna(subset=['商品条码'])
|
df_clean = df_clean.dropna(subset=['商品条码'])
|
||||||
out_dir = os.path.dirname(file_path)
|
out_dir = os.path.dirname(file_path)
|
||||||
final_path = os.path.join(out_dir, "预处理之后.xlsx")
|
final_path = os.path.join(out_dir, "预处理之后.xlsx")
|
||||||
@ -139,7 +148,7 @@ class OrderService:
|
|||||||
return final_path
|
return final_path
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"预处理识别失败: {e}")
|
logger.warning(f"智能预处理识别失败: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_purchase_orders(self) -> List[str]:
|
def get_purchase_orders(self) -> List[str]:
|
||||||
|
|||||||
95
启动器.py
95
启动器.py
@ -1582,99 +1582,12 @@ def merge_orders_with_status(log_widget, status_bar):
|
|||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
def process_tobacco_orders_with_status(log_widget, status_bar):
|
def process_tobacco_orders_with_status(log_widget, status_bar):
|
||||||
"""处理烟草订单"""
|
"""处理烟草订单 (已统一走智能识别流程)"""
|
||||||
def run_in_thread():
|
process_excel_file_with_status(log_widget, status_bar)
|
||||||
try:
|
|
||||||
reporter = ProgressReporter(status_bar)
|
|
||||||
reporter.running()
|
|
||||||
reporter.set("正在处理烟草订单...", 10)
|
|
||||||
add_to_log(log_widget, "开始处理烟草订单\n", "info")
|
|
||||||
|
|
||||||
init_gui_logger(log_widget)
|
|
||||||
|
|
||||||
# 创建烟草服务实例
|
|
||||||
config_manager = ConfigManager()
|
|
||||||
tobacco_service = TobaccoService(config_manager)
|
|
||||||
|
|
||||||
# 执行烟草订单处理
|
|
||||||
result = tobacco_service.process_tobacco_order()
|
|
||||||
|
|
||||||
if result:
|
|
||||||
add_to_log(log_widget, "烟草订单处理完成\n", "success")
|
|
||||||
try:
|
|
||||||
add_recent_file(result)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
add_to_log(log_widget, "烟草订单处理失败\n", "error")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
add_to_log(log_widget, f"烟草订单处理出错: {str(e)}\n", "error")
|
|
||||||
finally:
|
|
||||||
dispose_gui_logger()
|
|
||||||
reporter.done()
|
|
||||||
|
|
||||||
# 在新线程中运行
|
|
||||||
thread = Thread(target=run_in_thread)
|
|
||||||
thread.daemon = True
|
|
||||||
thread.start()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def process_rongcheng_yigou_with_status(log_widget, status_bar):
|
def process_rongcheng_yigou_with_status(log_widget, status_bar):
|
||||||
def run_in_thread():
|
"""处理蓉城易购订单 (已统一走智能识别流程)"""
|
||||||
try:
|
process_excel_file_with_status(log_widget, status_bar)
|
||||||
reporter = ProgressReporter(status_bar)
|
|
||||||
reporter.running()
|
|
||||||
add_to_log(log_widget, "开始处理蓉城易购\n", "info")
|
|
||||||
|
|
||||||
s = load_user_settings()
|
|
||||||
out_dir = os.path.abspath(s.get('output_folder', 'data/output'))
|
|
||||||
candidates = []
|
|
||||||
if os.path.exists(out_dir):
|
|
||||||
for f in os.listdir(out_dir):
|
|
||||||
if re.match(r'^订单\d+\.xlsx$', f.lower()):
|
|
||||||
p = os.path.join(out_dir, f)
|
|
||||||
candidates.append((p, os.path.getmtime(p)))
|
|
||||||
|
|
||||||
if not candidates:
|
|
||||||
add_to_log(log_widget, "未在输出目录找到蓉城易购订单文件\n", "warning")
|
|
||||||
reporter.done()
|
|
||||||
return
|
|
||||||
|
|
||||||
candidates.sort(key=lambda x: x[1], reverse=True)
|
|
||||||
src_path = candidates[0][0]
|
|
||||||
|
|
||||||
from app.services.special_suppliers_service import SpecialSuppliersService
|
|
||||||
service = SpecialSuppliersService(ConfigManager())
|
|
||||||
|
|
||||||
result = service.process_rongcheng_yigou(
|
|
||||||
src_path,
|
|
||||||
progress_cb=lambda p, m: (reporter.set(m, p), add_to_log(log_widget, f"{m}\n", "info"))
|
|
||||||
)
|
|
||||||
|
|
||||||
if result:
|
|
||||||
add_to_log(log_widget, f"处理完成: {result}\n", "success")
|
|
||||||
add_recent_file(result)
|
|
||||||
try:
|
|
||||||
validate_unit_price_against_item_data(result, log_widget)
|
|
||||||
except Exception: pass
|
|
||||||
open_result_directory_from_settings()
|
|
||||||
reporter.set("处理完成", 100)
|
|
||||||
else:
|
|
||||||
add_to_log(log_widget, "处理失败\n", "error")
|
|
||||||
except Exception as e:
|
|
||||||
add_to_log(log_widget, f"处理出错: {str(e)}\n", "error")
|
|
||||||
finally:
|
|
||||||
reporter.done()
|
|
||||||
|
|
||||||
thread = Thread(target=run_in_thread)
|
|
||||||
thread.daemon = True
|
|
||||||
thread.start()
|
|
||||||
thread = Thread(target=run_in_thread)
|
|
||||||
thread.daemon = True
|
|
||||||
thread.start()
|
|
||||||
|
|
||||||
def process_excel_file_with_status(log_widget, status_bar):
|
def process_excel_file_with_status(log_widget, status_bar):
|
||||||
"""处理Excel文件"""
|
"""处理Excel文件"""
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user