Initial commit: Auto-Finance 财务报销自动化系统
This commit is contained in:
128
app/pipeline.py
Normal file
128
app/pipeline.py
Normal file
@@ -0,0 +1,128 @@
|
||||
"""
|
||||
报销全流程编排
|
||||
|
||||
将发票提取 → OCR 识别 → 浏览器填报串联为一条管道,
|
||||
数据在内存中流转,同时生成 CSV / Markdown 中间产物。
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from . import get_logger
|
||||
from .config import load_config
|
||||
from .extractor import extract_invoices, save_csv as save_invoice_csv, save_markdown as save_invoice_md
|
||||
from .ocr import enrich_with_ocr, _save_csv as save_ocr_csv, save_markdown_from_csv, _load_csv
|
||||
|
||||
log = get_logger("pipeline")
|
||||
|
||||
|
||||
def run_pipeline(step: str = "all", username: str = None, password: str = None):
|
||||
"""执行报销流程
|
||||
|
||||
Args:
|
||||
step: all | invoice | ocr | submit
|
||||
username: 覆盖 config.json 中的用户名
|
||||
password: 覆盖 config.json 中的密码
|
||||
"""
|
||||
config = load_config()
|
||||
if username:
|
||||
config["username"] = username
|
||||
if password:
|
||||
config["password"] = password
|
||||
|
||||
# 工作目录(项目根目录)
|
||||
project_dir = Path(__file__).parent.parent
|
||||
|
||||
# --------------------------------------------------
|
||||
# Step 1: 发票提取
|
||||
# --------------------------------------------------
|
||||
invoices = None
|
||||
|
||||
if step in ("all", "invoice"):
|
||||
log.info("=" * 60)
|
||||
log.info("[1/3] 发票提取")
|
||||
log.info("=" * 60)
|
||||
|
||||
invoices = extract_invoices(str(project_dir))
|
||||
if not invoices:
|
||||
log.error("未提取到任何发票数据")
|
||||
return 1
|
||||
|
||||
save_invoice_csv(invoices, project_dir / "invoice_summary.csv")
|
||||
save_invoice_md(invoices, project_dir / "invoice_summary.md")
|
||||
|
||||
if step == "invoice":
|
||||
log.info("[1/3] 发票提取 完成")
|
||||
return 0
|
||||
|
||||
# --------------------------------------------------
|
||||
# Step 2: OCR 识别
|
||||
# --------------------------------------------------
|
||||
if step in ("all", "ocr"):
|
||||
log.info("=" * 60)
|
||||
log.info("[2/3] OCR 识别")
|
||||
log.info("=" * 60)
|
||||
|
||||
csv_path = project_dir / "invoice_summary.csv"
|
||||
|
||||
if invoices is None:
|
||||
rows = _load_csv(csv_path)
|
||||
if rows is None:
|
||||
return 1
|
||||
else:
|
||||
# 将 dict 列表转为 CSV 风格的 dict(对齐列名)
|
||||
from .extractor import CSV_COLUMNS
|
||||
rows = []
|
||||
for idx, inv in enumerate(invoices, 1):
|
||||
items = inv.get("_items", [])
|
||||
first_item = items[0] if items else {}
|
||||
rows.append({
|
||||
"序号": str(idx),
|
||||
"发票号码": inv.get("发票号码", ""),
|
||||
"开票日期": inv.get("开票日期", ""),
|
||||
"项目名称": first_item.get("项目名称", inv.get("项目名称", "")),
|
||||
"规格型号": first_item.get("规格型号", inv.get("规格型号", "")),
|
||||
"价税合计": inv.get("价税合计", ""),
|
||||
"销售方名称": inv.get("销售方名称", ""),
|
||||
"人员姓名": inv.get("人员姓名", ""),
|
||||
"刷卡日期": inv.get("刷卡日期", ""),
|
||||
"公务卡号": inv.get("公务卡号", ""),
|
||||
"刷卡金额": inv.get("刷卡金额", ""),
|
||||
"备注": inv.get("备注", ""),
|
||||
"工号": inv.get("工号", ""),
|
||||
})
|
||||
|
||||
rows = enrich_with_ocr(rows, str(project_dir))
|
||||
save_ocr_csv(csv_path, rows)
|
||||
save_markdown_from_csv(csv_path, rows)
|
||||
invoices = rows
|
||||
|
||||
if step == "ocr":
|
||||
log.info("[2/3] OCR 识别 完成")
|
||||
return 0
|
||||
|
||||
# --------------------------------------------------
|
||||
# Step 3: 浏览器填报
|
||||
# --------------------------------------------------
|
||||
if step in ("all", "submit"):
|
||||
log.info("=" * 60)
|
||||
log.info("[3/3] 报销提交")
|
||||
log.info("=" * 60)
|
||||
|
||||
from .bot import load_invoice_data, run_bot
|
||||
|
||||
csv_path = project_dir / "invoice_summary.csv"
|
||||
bot_invoices = load_invoice_data(str(csv_path), config)
|
||||
run_bot(config, bot_invoices)
|
||||
|
||||
if step == "submit":
|
||||
log.info("[3/3] 报销提交 完成")
|
||||
return 0
|
||||
|
||||
# --------------------------------------------------
|
||||
# 全流程完成
|
||||
# --------------------------------------------------
|
||||
log.info("=" * 60)
|
||||
log.info("全流程执行完毕")
|
||||
log.info("=" * 60)
|
||||
return 0
|
||||
Reference in New Issue
Block a user