Files
cma-management/docs/财务Bot网银流水自助入库流程.md

161 lines
8.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 财务Bot网银流水自助入库流程
> 适用:每月出纳导出银行/现金流水 → 按模板整理 xlsx → 财务Bot调用导入 API → 三校验 → 入库 → 现金流KPI联动 → 看板可见。
> 方案文档:`docs/网银流水导入方案-20260828.md` 后端代码:`backend/app/api/cash.py`(网银流水标准导入区)
---
## 一、流程总览
```
出纳导出网银流水(Excel)
按模板整理 xlsx(列:凭证日期/凭证号/科目编码/科目名称/借方金额/贷方金额/摘要)
① 下载模板 GET /api/cma/cash/import/template (模板缺失时参考)
② 导入 POST /api/cma/cash/import/vouchers multipart file + entity_id
三校验:① 借贷平衡(容差0.01) ② 期间合计 ③ 结转行识别
入库:voucher_details(凭证明细)+ import_logs(导入日志)
现金流联动:现金余额自动更新 + EXT_现金类KPI + F_CASH_SAFETY 现金安全垫KPI
看板可见:GET /api/cma/cash/balance、/api/cma/cash/dashboard
```
---
## 二、模板字段说明
模板下载:`GET /api/cma/cash/import/template`(需登录态,返回 xlsx 附件)。
| 列名 | 字段 | 必填 | 说明 |
|------|------|------|------|
| 凭证日期 | voucher_date | ✅ | 日期格式(Excel日期/文本均可,如 2026-08-01 |
| 凭证号 | voucher_no | ✅ | 如 `记-001` |
| 科目编码 | subject_code | ✅ | 如 `1002``1001``1122`**1001/1002 开头视为货币资金科目**(现金流联动依据) |
| 科目名称 | subject_name | ✅ | 如 `银行存款-工行` |
| 借方金额 | debit_amount | 条件 | 数字,可含千分位逗号;与贷方二选一 |
| 贷方金额 | credit_amount | 条件 | 数字,可含千分位逗号;与借方二选一 |
| 摘要 | summary | 条件 | 含"结转"或科目名含"本年利润"/"结转" → 识别为结转行 |
> 列名兼容中英文别名(如 `date`/`voucher_date`、`借方`/`debit_amount` 等,不区分大小写),但建议严格使用模板列名。
> 模板为单示例行,导入前删除示例行或直接覆盖为真实流水。
---
## 三、curl 命令示例
### 1. 登录拿 tokenadmin/admin123,账套 entity_id=1 酣客)
```bash
TOKEN=$(curl -s -X POST http://127.0.0.1:8010/api/cma/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123","entity_id":1}' \
| python3 -c "import sys,json;print(json.load(sys.stdin)['token'])")
echo "$TOKEN" # 响应字段含 token/entity_id/entity_name/user
```
### 2. 下载导入模板
```bash
curl -s -o 网银流水导入模板.xlsx \
-H "Authorization: Bearer $TOKEN" \
http://127.0.0.1:8010/api/cma/cash/import/template
ls -la 网银流水导入模板.xlsx # 应 >1000 字节
```
### 3. 导入网银流水(multipart 上传)
```bash
curl -s -X POST http://127.0.0.1:8010/api/cma/cash/import/vouchers \
-H "Authorization: Bearer $TOKEN" \
-F "entity_id=1" \
-F "file=@/path/to/2026年08月网银流水.xlsx"
```
### 4. 看板核对
```bash
curl -s -H "Authorization: Bearer $TOKEN" "http://127.0.0.1:8010/api/cma/cash/balance?entity_id=1"
curl -s -H "Authorization: Bearer $TOKEN" "http://127.0.0.1:8010/api/cma/cash/dashboard?entity_id=1"
```
---
## 四、三校验规则(导入时自动执行)
| # | 规则 | 逻辑 | 不通过时 |
|---|------|------|----------|
| ① | **借贷平衡** | Σ借方 = Σ贷方,容差 **0.01** | 返回 `balance_check.passed=false`errors 追加 `借贷不平衡: 借方合计X ≠ 贷方合计Y,差额Z`(仍入库其余行,部分成功模式) |
| ② | **期间合计** | 按 `period`(YYYY-MM)汇总借方/贷方合计,返回 `period_totals`,供对账 | 不阻断,仅展示 |
| ③ | **结转行识别** | 摘要含"结转" 或 科目名含"本年利润"/"结转" → `carry_forward=1`,**不参与现金流余额计算** | 不阻断,返回 `carry_forward_count` |
> 逐行校验(失败行记录 errors,不阻断整体):凭证日期为空/无法解析、凭证号为空、科目编码为空、科目名称为空、金额非数字、金额为负、借贷同时为0 → 该行跳过,其余行照常入库(**部分成功模式**)。
---
## 五、入库内容
- **voucher_details 表**(凭证明细):voucher_no / voucher_date / subject_code / subject_name / debit_amount / credit_amount / summary / carry_forward / period / batchbatch = 文件名_时间戳)
- **import_logs 表**(导入日志):filename / batch / total_rows / success_rows / failed_rows / errors(明细JSON/ period / import_type="vouchers" / created_by="finance-bot"
返回体示例:
```json
{
"success": true,
"total": 120, "success_rows": 118, "failed_rows": 2,
"errors": [{"row": 5, "field": "voucher_date", "reason": "日期无法解析: xxx"}],
"balance_check": {"passed": true, "debit_total": 123456.78, "credit_total": 123456.78, "diff": 0.0, "tolerance": 0.01},
"period_totals": {"2026-08": {"debit_total": 123456.78, "credit_total": 123456.78}},
"carry_forward_count": 2,
"cash_balance": 88.88,
"kpi_updates": [{"kpi_code": "EXT_069", "kpi_name": "库存现金", "period": "2026-08", "value": ...}, ...],
"batch": "2026年08月网银流水_20260828153000",
"entity_id": 1
}
```
---
## 六、现金流联动(导入成功自动触发)
1. **现金余额自动更新**:汇总 1001/1002 开头科目(排除结转行)`Σ借 - Σ贷` 得货币资金期末余额(元)→ `set_current_cash_balance`(万元)→ `GET /api/cma/cash/balance``current_cash` 实时反映
2. **EXT_现金类KPI**:名称含"现金"/"货币资金"的 active KPI(排除 F_CASH_SAFETY)写入/更新 `kpi_values`source_type="ledger"、data_status="verified"、remark 记录批次与明细口径)——库存现金类→1001余额,银行类→1002余额,其余→货币资金总额
3. **F_CASH_SAFETY 现金安全垫KPI**(万元):不存在则自动创建(formula=货币资金余额-短期借款);短期借款取 EXT_139 最新实际值(单位元÷10000),无数据时安全垫=货币资金余额
---
## 七、常见错误处理
| 现象 | 原因 | 处理 |
|------|------|------|
| 返回 `借贷不平衡: 借方合计X ≠ 贷方合计Y`balance_check.passed=false | 流水有遗漏/金额录错 | 核对 Excel 借贷金额,修正后重新导入(余额按最新批次重算,重复导入不叠加) |
| HTTP 400 `缺少必要列: ...` | 列名与模板不一致(如"日期"未被别名命中、列名带空格/全半角差异) | 对照模板列名重命名表头,或使用 `_VOUCHER_COL_ALIASES` 支持的别名 |
| HTTP 400 `无法读取Excel文件` | 文件损坏/非xlsx/加密 | 用 WPS/Excel 另存为 .xlsx 后再传 |
| HTTP 400 `Excel文件为空(无数据行)` | 工作表无数据 | 删除空sheet或填入数据 |
| errors 含 `日期无法解析` | 凭证日期为文本/格式异常 | 改成标准日期格式(如 2026-08-01 |
| errors 含 `金额不能为负` / `借贷金额不能同时为0` | 数据录入问题 | 修正对应行(失败行不会入库) |
| errors 含 `凭证号为空` / `科目编码为空` / `科目名称为空` | 缺单元格 | 补全后重导 |
| HTTP 401 | token 失效/未登录 | 重新登录拿 token;注意登录必须带 entity_id |
| HTTP 403 | 账号未授权该 entity_id | 联系管理员在 user_entities 授权 |
| 模板下载 404 | 模板文件缺失 | 检查 `backend/scripts/templates/网银流水导入模板.xlsx` 是否存在,或运行 `backend/scripts/gen_voucher_import_template.py` 重新生成 |
---
## 八、注意事项
- 导入是**增量写入**:同一文件重复导入会生成多条记录(batch 不同),余额按最新 batch 重算;对账以 `batch` 为粒度
- 结转行不参与现金流余额计算,但会计入借贷平衡校验
- 现金流联动失败不阻断入库(已入库数据保留,KPI 联动失败记 error 日志),可联系全栈Bot排查 `journalctl -u cma-backend`