8.0 KiB
8.0 KiB
财务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. 登录拿 token(admin/admin123,账套 entity_id=1 酣客)
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. 下载导入模板
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 上传)
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. 看板核对
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 / batch(batch = 文件名_时间戳)
- import_logs 表(导入日志):filename / batch / total_rows / success_rows / failed_rows / errors(明细JSON)/ period / import_type="vouchers" / created_by="finance-bot"
返回体示例:
{
"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
}
六、现金流联动(导入成功自动触发)
- 现金余额自动更新:汇总 1001/1002 开头科目(排除结转行)
Σ借 - Σ贷得货币资金期末余额(元)→set_current_cash_balance(万元)→GET /api/cma/cash/balance的current_cash实时反映 - EXT_现金类KPI:名称含"现金"/"货币资金"的 active KPI(排除 F_CASH_SAFETY)写入/更新
kpi_values(source_type="ledger"、data_status="verified"、remark 记录批次与明细口径)——库存现金类→1001余额,银行类→1002余额,其余→货币资金总额 - 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