返回文章列表
审计轨迹 Audit Trail

导出审计:内部汇总状态和导出证据不一致时怎么收口

盘点工具做到导出时,很容易把问题想简单:把数据库里的行查出来,生成 CSV 或表格。

这条路很快会出问题。内部汇总里有底表商品、底表外盘盈、手工数量、串号明细、作废事件、待复核状态;给一线人员看的结果表只需要商品、账面数量、实盘数量和差异。给管理员看的审计文件又要能追到每一次扫码、每一次数量录入和每一次作废。

如果每个导出接口各算一遍,迟早会出现口径不一致:页面上显示待填数量,导出里却是 0;SN 明细里事件被作废了,SKU 汇总还把它算进去;差异表只看底表商品,漏掉了底表外盘盈。

我后来把导出前移了一步:先生成一份汇总投影,再让不同导出从这份投影里取自己需要的字段。

简化后是这个结构:

scan_events
manual_quantity_counts
out_of_baseline_reviews
count_mode_snapshots
baseline_items
  -> summary_projection
  -> readable_result.xlsx
  -> sku_summary.csv
  -> sn_detail.csv
  -> audit.json

重点不是文件格式,而是 summary_projection。它把各种事实先收成统一语义:某个商品的账面数量是多少,串号计数是多少,手工数量是多少,最终实盘数量是多少,差异是什么,当前结果状态是什么。

然后再决定每个导出长什么样。

给复核人员看的表要克制。它不需要暴露事件 ID,也不需要把内部状态原样倒出来。它只需要回答几个问题:这是什么商品,账面多少,实盘多少,差异是什么。

审计向的导出要相反。它要保留足够多的细节,让之后能解释某个数量是怎么来的。尤其是作废事件,不能从明细里消失;它不再计数,但仍然是事实链的一部分。

我给自己留了一个检查表:

同一个商品在页面汇总和导出汇总中,counted_qty 是否一致?
作废事件是否不再影响 counted_qty?
作废事件是否仍出现在 SN 明细里?
数量盘点商品是否显示 pending 或 saved,而不是被当成 0?
底表外盘盈是否进入差异和审计快照?

这几个问题比”导出接口能不能下载”更有用。能下载只说明接口活着,不说明口径可信。

还有一个小细节:面向人的表格和面向审计的文件不应该互相污染。前者可以用中文差异标签,可以隐藏内部字段;后者应该保留稳定字段名和事件来源。把两者合成一个”万能导出”,最后往往是谁都不好用。

这次复盘以后,我对导出的理解变了。导出不是最后一步的格式化,而是对系统事实的一次公开承诺。页面、CSV、明细和审计 JSON 可以服务不同读者,但不能讲不同版本的故事。