4. 总账与明细账数据一致性核对

任务说明

本案例实现总账与明细账的一致性核对:读取总账(科目、期间、期初余额、期末余额)与明细账(科目、期间、借方发生额、贷方发生额),按“科目+期间”汇总明细账发生额,计算明细账推算的期末余额(期初余额 + 借方 - 贷方),再与总账期末余额比对,标记差异科目。

环境与依赖

  • Python 3.8+,依赖 pandas:pip install pandas
  • 输入为两个 CSV 文件:general_ledger.csv、detail_ledger.csv

输入数据示例

总账 general_ledger.csv:

科目,期间,期初余额,期末余额
1001,2024-01,10000,12000
1002,2024-01,5000,4500
1001,2024-02,12000,15000

明细账 detail_ledger.csv:

科目,期间,借方发生额,贷方发生额
1001,2024-01,3000,1000
1002,2024-01,500,1000
1001,2024-02,4000,1000

核对逻辑

总账 科目+期间+期末余额 明细账 科目+期间+借贷发生额 按科目+期间汇总 推算期末余额 比对期末余额 标记差异科目

完整代码

import pandas as pd

def reconcile(gl_path, dl_path, tol=0.01):
    gl = pd.read_csv(gl_path, dtype={"科目": str})
    dl = pd.read_csv(dl_path, dtype={"科目": str})

    # 按科目+期间汇总明细账发生额
    agg = dl.groupby(["科目", "期间"], as_index=False).agg(
        借方发生额=("借方发生额", "sum"),
        贷方发生额=("贷方发生额", "sum"),
    )

    # 合并总账与明细账汇总
    merged = gl.merge(agg, on=["科目", "期间"], how="outer")

    # 明细账推算期末余额 = 期初余额 + 借方 - 贷方
    merged["推算期末余额"] = (
        merged["期初余额"].fillna(0)
        + merged["借方发生额"].fillna(0)
        - merged["贷方发生额"].fillna(0)
    )

    # 差异 = 总账期末余额 - 推算期末余额
    merged["差异"] = merged["期末余额"].fillna(0) - merged["推算期末余额"]
    merged["是否一致"] = merged["差异"].abs() <= tol

    diff = merged[~merged["是否一致"]].copy()
    return merged, diff

if __name__ == "__main__":
    merged, diff = reconcile("general_ledger.csv", "detail_ledger.csv")
    print("=== 全部核对结果 ===")
    print(merged[["科目", "期间", "期末余额", "推算期末余额", "差异", "是否一致"]])
    print("\n=== 差异科目 ===")
    if diff.empty:
        print("无差异,全部一致")
    else:
        print(diff[["科目", "期间", "期末余额", "推算期末余额", "差异"]])

运行与验证

  1. 将上述两个 CSV 与脚本放在同一目录,执行 python reconcile.py。
  2. 观察输出:是否一致 为 True 表示该科目该期间总账与明细账一致;为 False 的行即差异科目。
  3. 以上述示例数据为例,1002 科目 2024-01 推算期末余额为 5000+500-1000=4500,与总账 4500 一致;若将明细账 1002 借方改为 600,则推算为 4600,与总账 4500 差异 -100,会被标记为差异科目。
  4. 通过条件:差异科目列表与人工核对结果一致,且一致科目差异绝对值不超过容差 tol。