fix: 智能导入列检测+名称防护 — 科目编码误当名称(EXT_069显示1001.0/EXT_071显示nan)根因修复
- kpi_code_patterns 名称类列优先(科目名称/指标名称/name),编码类列兜底 - 修复科目余额表表头(科目编码|科目名称)检测失败fallback cols[0]导致名称存成编码 - 导入循环增加防护: NaN/空/纯数字名称跳过,不再创建垃圾KPI - 存量数据: 14个一级科目名称已按科目表修正,82个明细标记待财务核对,EXT_071标记未命名
This commit is contained in:
+14
-6
@@ -80,11 +80,11 @@ async def import_excel(file: UploadFile = File(...),
|
||||
# ── 智能导入(BOT自动识别,无需手动映射) ──
|
||||
|
||||
_SMART_MAP = {
|
||||
# KPI编码列匹配模式 → 标准kpi_code
|
||||
# KPI名称/编码列匹配模式(顺序重要:名称类列优先,避免科目编码被当名称)
|
||||
"kpi_code_patterns": [
|
||||
re.compile(r'^(kpi_?code|指标编码|编码)$', re.I),
|
||||
re.compile(r'^(科目|项目|账户|报表项目|项目名称)$'),
|
||||
re.compile(r'^(指标名称?|kpi名称?|name)$', re.I),
|
||||
re.compile(r'^(科目名称|项目名称|指标名称?|kpi名称?|name|名称)$', re.I),
|
||||
re.compile(r'^(科目编码|科目代码|kpi_?code|指标编码|编码)$', re.I),
|
||||
re.compile(r'^(科目|项目|账户|报表项目)$'),
|
||||
],
|
||||
# 期间列匹配
|
||||
"period_patterns": [
|
||||
@@ -218,11 +218,19 @@ async def import_excel_smart(
|
||||
skipped_rows = []
|
||||
|
||||
for idx, row in df.iterrows():
|
||||
raw_kpi = str(row.get(kpi_col, "")).strip()
|
||||
raw_kpi_raw = row.get(kpi_col, "")
|
||||
raw_kpi = str(raw_kpi_raw).strip()
|
||||
raw_val = row.get(value_col)
|
||||
raw_period = str(row.get(period_col, period or "")).strip() if period_col else (period or "")
|
||||
|
||||
if not raw_kpi or pd.isna(raw_val):
|
||||
# 名称防护:NaN/空/None 或 纯数字(疑似科目编码被误当名称)→ 跳过,避免创建垃圾KPI
|
||||
if raw_kpi.lower() in ("nan", "none") or not raw_kpi:
|
||||
skipped_rows.append(f"第{idx+2}行: KPI名称为空")
|
||||
continue
|
||||
if re.fullmatch(r"\d+(\.\d+)?", raw_kpi):
|
||||
skipped_rows.append(f"第{idx+2}行: KPI名称疑似科目编码「{raw_kpi}」,跳过")
|
||||
continue
|
||||
if pd.isna(raw_val):
|
||||
skipped_rows.append(f"第{idx+2}行: 缺数据")
|
||||
continue
|
||||
if not raw_period:
|
||||
|
||||
Reference in New Issue
Block a user