fix: 智能导入——匹配不上的财务报表科目自动创建KPI定义

- 清理科目前缀(一、/减:/加:)后多级匹配
- ⑤仍未匹配→自动创建KPI(PL_001/CF_001/BS_001)
- 避免205条全部跳过的场景
This commit is contained in:
Hermes CI Fix
2026-07-29 18:02:50 +08:00
parent 8a7cf25025
commit 9b973ab9a8
2 changed files with 118 additions and 13 deletions
+47 -13
View File
@@ -190,10 +190,16 @@ async def import_excel_smart(file: UploadFile = File(...), db: Session = Depends
for code in known_codes:
clean = re.sub(r'[\s\-_()()]', '', code).lower()
alias_map[clean] = code
# 中文名映射("营业收入"→F_REVENUE
name_map: dict[str, str] = {}
for code, kpi_obj in kpis.items():
name_map[kpi_obj.kpi_name] = code
# 8. 遍历导入
# 8. 遍历导入(匹配不上的自动创建KPI
stype_prefix = {"PL": "PL_", "CF": "CF_", "BS": "BS_"}.get(stype or "", "EXT_")
batch = hashlib.md5(str(datetime.now().timestamp()).encode()).hexdigest()[:12]
imported = 0
created_kpis = 0
skipped_rows = []
for idx, row in df.iterrows():
@@ -208,24 +214,50 @@ async def import_excel_smart(file: UploadFile = File(...), db: Session = Depends
skipped_rows.append(f"{idx+2}行: 无法确定期间")
continue
# 智能匹配KPI编码
# 清理科目名(去掉"一、""减:""加:"等前缀)
clean_name = re.sub(r'^[一二三四五六七八九十、\s\+]+', '', raw_kpi)
clean_name = re.sub(r'^[减加]?[:]\s*', '', clean_name).strip()
if not clean_name:
clean_name = raw_kpi
# 匹配KPI
kpi_code = None
# ① 精确编码匹配(极少情况)
if raw_kpi in known_codes:
kpi_code = raw_kpi
else:
# 别名匹配
# ② 别名匹配(去符号小写)
if not kpi_code:
clean_key = re.sub(r'[\s\-_()()]', '', raw_kpi).lower()
kpi_code = alias_map.get(clean_key)
# 模糊匹配(中文科目名→KPI编码)
if not kpi_code:
for code, kpi_obj in kpis.items():
if raw_kpi in kpi_obj.kpi_name or kpi_obj.kpi_name in raw_kpi:
kpi_code = code
break
# ③ 中文名精确匹配
if not kpi_code:
skipped_rows.append(f"{idx+2}行: 「{raw_kpi}」未匹配到KPI")
continue
kpi_code = name_map.get(clean_name)
# ④ 中文名模糊匹配
if not kpi_code:
for code, kpi_obj in kpis.items():
if clean_name in kpi_obj.kpi_name or kpi_obj.kpi_name in clean_name:
kpi_code = code
break
# ⑤ 仍未匹配 → 自动创建KPI
if not kpi_code:
new_code = f"{stype_prefix}{len(kpis) + created_kpis + 1:03d}"
new_kpi = KPIDefinition(
kpi_code=new_code,
kpi_name=clean_name,
dimension="finance",
category="financial_report",
data_source_type="excel",
status="active",
)
db.add(new_kpi)
db.flush()
kpis[new_code] = new_kpi
known_codes.add(new_code)
name_map[clean_name] = new_code
kpi_code = new_code
created_kpis += 1
try:
val = float(raw_val)
@@ -248,6 +280,8 @@ async def import_excel_smart(file: UploadFile = File(...), db: Session = Depends
# 9. 返回汇总
stype_label = {"PL": "利润表", "CF": "现金流量表", "BS": "资产负债表"}.get(stype or "", "数据表")
msg = f"{stype_label}识别成功,导入{imported}"
if created_kpis:
msg += f",自动创建{created_kpis}个新KPI"
if skipped_rows:
msg += f"{len(skipped_rows)}条跳过:\n" + "\n".join(skipped_rows[:8])
if len(skipped_rows) > 8: