--- name: bank-flow-reconciliation description: >- 银行流水合并与核对工具。支持多银行多格式流水文件的智能合并(标准化为统一12列格式), 以及银行流水与序时账(总账)的自动化双向核对(9层递进匹配引擎)。 当用户提到"银行流水核对""流水核对""银行流水合并""合并流水""流水匹配""银行存款核对" "对账""核对银行流水""bank reconciliation""流水对账""多账号流水合并""银行流水审计" "核对银行存款""序时账核对"时触发。 即使用户只说"帮我核对下银行流水"或"把这几个银行的流水合到一起"也应触发。 审计场景中涉及银行存款测试、资金核对时优先使用此 skill。 slug: nigo-bank-flow-reconciliation displayName: 银行流水合并核对 version: 1.0.0 summary: 银行流水合并与核对工具,9层递进匹配引擎,支持多银行多格式流水合并与序时账自动双向核对,输出审计底稿。 license: MIT --- > **作者**:nigo(涂佳兵) | **微信公众号**:逆行的狗 > > 审计实务 + 数字化工具,分享审计效率提升的实战经验。 # 银行流水合并与核对 ## 概述 三个脚本,按工作流顺序: 1. **预检查** (`scripts/bankflow_precheck.py`):读取文件,输出列名、样本行、金额统计、科目分布。只探查不判断。 2. **流水合并** (`scripts/bankflow_merge.py`):多银行多格式流水 → 统一12列标准化Excel 3. **流水核对** (`scripts/bankflow_reconcile.py`):银行流水 vs 序时账,9层递进匹配,输出核对底稿 AI 的工作:运行脚本 → 看输出 → 填配置 → 运行脚本 → 问用户要不要 AI 复核。匹配逻辑全在代码里,AI 不需要理解引擎内部。 ## 数据准备 核对需要两份数据:**序时账**(总账/明细账)和**银行流水**。 ### 序时账必需字段 | 要素 | 说明 | |------|------| | 银行存款科目行 | 科目代码通常以 1002 开头。无科目代码列时可用科目名称"银行存款"代替 | | 日期列 | 记账日期或凭证日期 | | 借方/贷方金额列 | 两列分开,不能只有一列带正负号的金额 | | 凭证号列 | 识别同一笔凭证的多行分录 | | 摘要列 | L2 匹配层的关键信息源 | | **客商信息** | ⭐ **决定性因素**。有客商→匹配率 90%+,无客商→30-50% | ### ⭐ 客商信息(两种来源,二选一) | 来源 | 配置 | 场景 | |------|------|------| | **①客商辅助核算列** | `客商辅助项列名: "客户,供应商"` | 用友/金蝶标准账套,客商在对方科目行的辅助核算项中(**拆分模式**) | | **②交易对手列** | `交易对手列名: "往来单位名称"` | 银行存款行上有独立的"往来单位"/"交易对手"列(**直接模式**,匹配率更高) | 直接模式实证 92.6%,拆分模式 78.5%。优先直接模式,银行存款行无客商值时才用拆分模式。 ### 银行流水必需字段 | 要素 | 说明 | |------|------| | 交易日期 | 每笔交易日期 | | 金额(借/贷 或 收/支) | 两列分开 | | 对方户名 | 强烈建议,与序时账客商交叉匹配 | | 摘要 | L2 匹配线索 | 文件格式 `.xlsx`/`.xls`/`.csv` 均可,表头不在第一行或尾部有汇总行都能处理。 --- ## 工作流程 ### 第1步:判断任务类型 - **仅合并**:多个银行流水 → 一个标准化Excel - **仅核对**:已有标准化流水 → 与序时账核对 - **合并+核对**:先合并再核对 用户说"核对"但提供了多个银行的流水文件 → 通常需要先合并。 ### 第2步:运行预检查 ```bash python SKILL_DIR/scripts/bankflow_precheck.py \ --gl "序时账.xlsx" \ --bank "银行流水.xls" \ --bank-subject "1002" ``` 输出:文件格式、列名、前3行样本、金额统计、**候选客商列诊断表**(列名+非空率+样本值)、银行科目分布、主体列分布。AI 看这些信息做第3步的判断。 > 常用参数:`--gl-subject-col`(科目代码列名)、`--bank-subject-name`(按名称过滤)、`--bank-header-row`(跳过前置行)。全表见 `references/配置参数详解.md`。 ### 第3步:做判断 看预检查输出,做 4 个决策: #### 决策1:列映射 根据列名和样本值确定配置中各字段对应哪列。看实际列名,不凭猜测——"科目编号"/"科目代码"/"科目编码"在不同软件中叫法不同。 **陷阱提醒**: - **无科目代码列**:用科目名称列代替,配 `科目代码列名: "科目名称"`, `银行科目代码: "银行存款"` - **科目代码混在编码列**(如"1002/8111001012600894851"):直接用该列,配 `银行科目代码: "1002"`,引擎 startswith 天然处理 - **假客商陷阱**:`交易对手`列 100% 非空但样本值是银行账户名(如"中国农业银行墨江县支行007316")→ 不是真客商。看样本值判断,不被非空率迷惑。真客商可能在对方科目行的复合字段中 #### 决策2:客商信息够不够? 看预检查的诊断表:候选客商列在银行存款行上有值 → 直接模式(`交易对手列名`)。只在对方科目行有值 → 拆分模式(`客商辅助项列名`)。 > **⓾ 客商缺失确认(STOP)** > > 如果所有候选列在两边都无值,或样本值是银行账户名等非客商信息——停下来用 `question` 工具问用户。 > > **为什么停**:匹配率会从 90%+ 暴跌到 30-50%,落差太大。用户需要知情同意——他可能更愿意先整理客商数据,而不是接受一个大半匹配不上的底稿。 > > - [A] 继续:仅用金额+日期匹配,接受低匹配率 > - [B] 补充字段:我指定正确的对手列 > - [C] 取消:先完善数据 #### 决策3:多账户覆盖了吗? 看预检查输出的账号分布。 单账户或两边账户一致 → 直接继续。 > **⓾ 多账户不完全覆盖确认(STOP)** > > 序时账有 5 个银行账户但流水只有 2 个——静默继续会让另外 3 个账户全部无法匹配,用户以为全核对过了实际只核了一部分。审计场景中这个认知差异是风险。 > > - [A] 仅核对匹配的账户:过滤序时账只保留有流水的 > - [B] 全部核对:不设账户列名,整体核对(匹配率偏低) > - [C] 补充流水:我补缺失的银行流水文件 **多账户标识不一致**:序时账用"招商银行",流水用账号"3960xxx"→ 分组键不匹配 → 0%。此时不设账户列名(选[B]),整体核对。 **公司列必须对称**:序时账有公司列但流水没有 → 0%。不要配 `公司列名`,改用 `主体过滤`。 **性能**:>5000 行时强烈建议设账户列名分组(16s vs 129s)。 #### 决策4:范围对齐了吗?(低匹配率首要原因) 看预检查的银行科目分布和主体分布。序时账范围明显大于流水时,大量记录无法匹配。 | 类型 | 典型场景 | 解决方案 | 实证 | |------|---------|---------|------| | 科目代码范围 | 序时账含32个银行科目,流水只有1个 | 精确限定 `银行科目代码: "100201"` | 16% → 99% | | 主体范围 | 序时账含11个主体,流水只有1个 | `主体过滤: "主体,西安德诺"` | 4% → 93% | | 日期范围 | 序时账全年,流水半年 | `日期范围: "2025-01-01,2025-06-30"` | 偏低→正常 | > **⓾ 范围限定确认(STOP)** > > 配 `主体过滤`/`日期范围` 或收窄 `银行科目代码` 前——被过滤的记录完全不参与核对,用户可能误以为全部核对过了。审计底稿遗漏记录而不披露是重大风险。 > > - [A] 确认限定:接受范围对齐后的高匹配率 > - [B] 保留全部:不限定,整体核对(匹配率偏低但不遗漏) 选 [A] 后才配置过滤参数。汇报结果时披露实际使用的过滤条件。 ### 第4步:写配置 根据判断结果写 `reconcile_config.json`。 > **完整参数表和 JSON 示例**见 `references/配置参数详解.md`(gl_config + bank_config 全字段、客商模式选择、从合并结果衔接核对的固定映射)。 ### 第5步:运行核对 ```bash python SKILL_DIR/scripts/bankflow_reconcile.py \ reconcile_config.json \ --output "输入文件所在目录/核对底稿.xlsx" ``` 不传 `--output` 默认保存到 CWD,文件名 `银行流水核对底稿_YYYYMMDD_HHMMSS.xlsx`。建议显式传 `--output`。 ### 第6步:AI 复核(可选) > **STOP — 运行完第5步后先停下来。不要自动加 `--ai-review` 重跑。** > > **为什么停下来问**:AI 复核逐条读未匹配记录(可能上百条),耗时 1-2 分钟和可观 token。但匹配率 90%+ 时,剩余十几条交给会计人工看反而更高效(他们有业务上下文)。自动复核 = 在用户不需要时浪费时间和钱。这是实际使用中最常被跳过的 gate——看到匹配率就想继续跑,但复核是可选的,选择权在用户。 读引擎输出的匹配率,用 `question` 工具问: > 当前匹配率:金额 99.2% / 条数 98.4%,未匹配 112 条。 > > - **[A] 进行 AI 复核**:逐条审查未匹配记录,可匹配的写入底稿(预计 1-2 分钟) > - **[B] 不复核**:直接出底稿,剩余交人工(推荐:匹配率已高) > - **[C] 先修范围/数据**:匹配率偏低时回到决策4 选 [A] 才进入 AI 复核(详见 `references/AI复核流程.md`)。未匹配 > 500 条时引擎自动跳过——说明范围没对齐,该修范围而不是硬复核。 --- ## 匹配率预期 | 场景 | 预期金额匹配率 | |------|-------------| | 范围对齐 + 有客商 | 90%~99%(正常) | | 范围对齐 + 无客商 + 有摘要 | 70%~90% | | 无客商 + 无摘要 | 30%~50% | | 范围不对齐 | <50%(先修范围) | **金额匹配率 ≥ 90% 就算好结果,不需要分析原因。** 条数匹配率通常低于金额匹配率——序时账把多笔小额费用报销汇总成一笔凭证是常态(如 50 笔银行流水对应 1 笔 GL),这会拉低条数匹配率但不影响核对结论。只要总额平衡(流水收支 ≈ 序时账借贷),底稿可以直接交付,未匹配记录交会计人工核视即可。**不要主动长篇分析匹配率不高的原因——用户要的是底稿,不是分析报告。** --- ## 依赖安装 ```bash pip install pandas openpyxl xlrd rapidfuzz ``` `xlrd` 仅在读 .xls 时需要。`rapidfuzz` 可选(回退到 difflib)。 --- ## 参考文档 | 文档 | 何时查阅 | |------|---------| | `references/配置参数详解.md` | 写配置时——三个模块全部参数表和 JSON 示例 | | `references/AI复核流程.md` | 执行 AI 复核时——按月分批、subagent 提示词、三个判断层次 |