# 财务数据通道方案：网银流水标准导入模板（P1）

- 提出：研学调度中枢（反向上报触发，2026-08-28）
- 执行：项目Bot（方案/验收/协调）→ 全栈Bot（开发）
- 背景：酣客现金流2.2万 vs 短债350万 = 全年最大风险，现金流监控空窗（不直连，靠手工）

## 一、ERP连通可行性结论（已完成摸底，2026-08-28）

| 检查项 | 结果 |
|--------|------|
| ERP网关容器 | 活着（erp-gateway Up 4 days，127.0.0.1:8300） |
| ERP真实数据库 | **不可达**：SQL Server 211.149.143.215 连接超时（pymssql OperationalError 20009） |
| ERP API 端点 | /stats/monthly、/cashflow 等全部 000/500 |
| erp_sync cron | 2026-08-19 已 PAUSED（#PAUSED-20260819） |
| kpi_values erp源数据 | 0 条（从未同步成功） |
| data_source_config | 12条ERP源配置存在但全部空转 |

**结论：ERP连通短期无望（真实ERP库在外部网络不可达），走方案②网银流水标准导入模板。**

## 二、现状盘点（基础设施大部分已就绪）

| 已有资产 | 状态 |
|----------|------|
| voucher_details 表（凭证明细） | ✅ 已建，0行。字段：voucher_no/voucher_date/subject_code/subject_name/debit_amount/credit_amount/summary/new_standard_category/period |
| import_logs 表（导入日志） | ✅ 已建，0行。字段：filename/batch/total_rows/success_rows/failed_rows/errors/period/import_type/created_by |
| VoucherDetail 模型 | ✅ 已注册（app/models/__init__.py:614） |
| /api/cma/cash/balance | ✅ 现金余额（手工基线） |
| /api/cma/cash/dashboard | ✅ 现金流看板 |
| /api/cma/cash/gap-forecast | ✅ 缺口预测 |
| /api/cma/cash/plans | ✅ 收付款计划 |
| DataManage.vue Excel导入tab | ✅ 已有（import-excel-smart，KPI导入） |
| 现金流KPI（EXT_202-208各店现金等） | ✅ 存在，2026-06有数据（手工Excel导入） |

**缺口（本次开发内容）**：无凭证/网银流水导入API、无校验规则（借贷平衡/期间合计/结转行识别）、无前端流水导入界面、现金流余额不自动更新。

## 三、开发内容（全栈Bot执行）

### 3.1 导入模板定义（xlsx）

模板列（与 voucher_details 字段对齐）：

| 列名 | 字段 | 必填 | 说明 |
|------|------|------|------|
| 凭证日期 | voucher_date | ✅ | YYYY-MM-DD 或 日期格式 |
| 凭证号 | voucher_no | ✅ | 字符串 |
| 科目编码 | subject_code | ✅ | 如 1002（银行存款） |
| 科目名称 | subject_name | ✅ | 如 银行存款-工行 |
| 借方金额 | debit_amount | 二选一 | 无则0 |
| 贷方金额 | credit_amount | 二选一 | 无则0 |
| 摘要 | summary | 可选 | 结转行识别依据 |

生成模板文件：`backend/scripts/templates/网银流水导入模板.xlsx`（含表头+1行示例）。

### 3.2 新入库接口 POST /api/cma/cash/import/vouchers

入参：multipart file + entity_id（Depends get_entity_id）+ period（可选，默认从文件名/日期提取）

处理流程：
1. 解析xlsx（openpyxl/pandas）
2. 逐行校验：日期可解析、科目编码/名称非空、金额为数字且≥0、借贷不全为0
3. 校验规则（核心）：
   - **借贷平衡**：Σ借方 = Σ贷方（容差 0.01），不平衡返回错误+差额
   - **期间合计**：按 period 汇总借方/贷方合计（用于对账展示）
   - **结转行识别**：摘要含"结转"或科目名称含"本年利润/结转" → 标记 carry_forward=True，不参与现金流计算
4. 写入 voucher_details（batch = 文件名_时间戳），period 从日期列提取
5. 写 import_logs（total/success/failed/errors 明细）
6. **现金流联动**：计算货币资金类科目（科目编码 1001/1002 开头）期末余额 → 调用 set_current_cash_balance → 同步更新 EXT_现金类KPI 实际值（写入 kpi_values，source_type=ledger）→ 看板可见

返回：{success, total, success_rows, failed_rows, errors[], 借贷平衡校验, 期间合计, 结转行数, 现金余额}

### 3.3 校验规则实现细节

- 借贷平衡容差：|Σ借-Σ贷| <= 0.01 通过
- 期间合计：返回 {period: {debit_total, credit_total}} 供对账
- 结转行识别：summary LIKE '%结转%' OR subject_name LIKE '%本年利润%' OR subject_name LIKE '%结转%'
- 失败行收集：{行号, 原因} 数组，不中断整体导入（部分成功模式）

### 3.4 前端：CashPlan.vue 增加"网银流水导入"tab

- el-tab-pane "流水导入"：上传xlsx → 调 import/vouchers → 显示校验结果（借贷平衡✅/❌、期间合计、成功/失败行、错误明细）→ 成功提示
- 注意：项目已知 el-dialog 坑，弹窗用 MyDialog；交互组件用原生 button
- 导入成功后刷新 cash dashboard（现金余额更新可见）

### 3.5 财务Bot自助入库流程（文档）

文档：`docs/财务Bot网银流水自助入库流程.md`
- 每月出纳导出网银流水 → 按模板整理xlsx
- 财务Bot调 POST /api/cma/cash/import/vouchers（curl 或脚本）
- 校验通过 → 入库 → 现金余额自动更新 → 看板可见
- 校验失败 → 按错误明细修正后重导

## 四、验收标准（铁律七：不验证=没做）

1. ERP可行性结论 ✅（已有：ERP库不可达，走②）
2. 模板文件存在：ls backend/scripts/templates/网银流水导入模板.xlsx
3. 校验规则跑通：构造测试xlsx（含借贷不平衡、结转行、正常行）实测三种规则
4. 入库接口可用：curl 导入 → SELECT voucher_details 有数据 → import_logs 有记录
5. 现金流联动：导入后 GET /api/cma/cash/balance 现金余额=货币资金科目余额，dashboard可见
6. 前端：CashPlan.vue 有"流水导入"tab，上传可导入
7. 文档：财务Bot自助入库流程文档存在
8. 无回归：/health 正常，已有cash端点正常

## 五、开发约束

- 代码库：/root/cma-management（后端 FastAPI + 前端 Vue3）
- 后端重启：systemctl restart cma-backend（禁止手动起 uvicorn）
- 前端部署：npm run build → cp -rf dist/* /var/www/cma/
- 完成后 git add 关键目录（backend/app/ frontend/src/）+ commit + push
- 数据库：MySQL cma 库，多租户 entity_id 隔离
