我们是东莞妥达信息(tudait.com),做精细化库存管理(WMS)与企业管理软件。下面这套做法来自我们在客户现场跑出来的规则,不是 PPT 上的制度。
先纠一个顺序
大部分公司「从零建库存管理」,第一步是买系统、或者找一份别家的制度模板。这两件事都不该排第一。
从零建政策,正确的顺序是三段:先定账的形状(数据模型)→ 再定流程与权限(谁能动什么)→ 最后才是系统实现。 顺序反了,结果一定是「制度一套、账一套」:纸面上要求批次管理,系统里只有一个总数;纸面上要求先审批后出库,系统里谁都能直接扣。
政策不是文档,政策是系统里跑得出来的规则。凡是系统不拦、只靠人自觉的条款,半年后都会失效——所以下面每一条,我都写成「规则 + 系统怎么保证」。
第 0 步:建账。但先明确「一行库存」必须能回答四个问题
从零的第一步不是管,是建账:把现有库存一次性登记清楚。别追求完美,先求「能回答四个问题」——每一行库存都必须能说清:
- 是什么(物料 + 规格)
- 在哪(仓库 + 存放地 + 管理人)
- 值多少(批次价格)
- 从哪来(来源单据:采购单 / 转入 / 拆分而来)
四个问题答不全的行,单独标记成「历史遗留批次」,不要为了好看编数据。编出来的账,比没有账更危险。
产出物就三样:《物料主档》《仓库与存放地清单》《库存批次清单》。规模小的公司,一张表就能起步;但表的结构必须按下面第 1、2 步来搭,否则后面全要返工。
第 1 步:身份体系——最容易被跳过,但决定这个政策能走多远
库存管不好,十次有八次是「身份没分清」。从零建政策,先把四种身份立起来:
- 物料身份:一个编码对应一个不可混淆的物料。同物不同规格、同物不同供应商,要么不同编码,要么在批次上区分清楚。含糊一次,后面所有报表都不可信。
- 位置身份:仓库 → 存放地 → 管理人,三级都要有名字。只写「在仓库」等于没写。
- 批次身份(关键):每次入库产生一个唯一 ID。我们叫 inID,它就是入库明细行的
_id。同一产品、同一批号,只要不是同一次入库,就是不同的批次行,账上不合并。 - 往来身份:供应商独立建档。同一产品从两家供应商进货,是两个批次、两个价格,不能混。
政策条文(示例):
所有库存必须以「批次行」形式存在;禁止对同一物料做跨批次的合并计数。每批次必须记录:来源单据、供应商、批号、入库时间、入库价格、经手仓管。
为什么这条最重要:批次身份决定了两件事能不能做——追溯(出了质量问题,能定位到批)和成本(每批一个价,出库成本才算得准)。这两件事没法事后补,只能从第一天就带上。
第 2 步:记账规则——「三态事件账」,这是政策的核心
传统库存表的形状是:一个产品一行,一个数量字段,入库 +、出库 −、盘点直接改数字。这个形状有三个天生缺陷:批次混在一起、可用与在库不分、花钱也追不回历史。从零建,别再用这个形状。
库存表里不允许出现「修改数量」这个动作。 数量只有三种状态的行:
| 行状态 | 含义 | 何时产生 |
|---|---|---|
status = 1 | 入库 | 入库单生效时新增一行 |
status = 0 | 冻结(预留) | 领用 / 销售确认时新增一行 |
status = -1 | 出库 | 出库时新增一行 |
余额完全由聚合得出,不维护:
可用数量 = Σ(status=1) − Σ(status=0) − Σ(status=-1)
冻结数量 = Σ(status=0)
实 数 = Σ(status=1) − Σ(status=-1) ← 真正躺在仓库里的
三个数字并存、分开显示。「在库 40、冻结 20、可用 20」和「在库 20」是完全不同的两件事,前者能解释货去哪了,后者只会让人以为货丢了。
配套三条纪律:
- 只追加,不修改:撤销、报损、盘点、拆分、转移,全都是再追加一行,用「方式」字段区分(采购入库 / 返仓 / 拆分 / 盘点入库 / 正常出库 / 报损 / 拆分出库 / 盘点出库 / 撤销 / 拒绝),再加一个有效性标记(有效 / 盘点 / 失效 / 撤销历史)。历史行永远在,只是被标记为不参与核算。
- 余额不做实体表:它是从原始行聚合出来的视图,所以永远和明细对得上,不存在「余额表忘了更新」。这是从零建账时最容易做错的一步——建实体余额表,等于埋一颗「迟早对不上」的雷。
- 出错必须可见:库存不足就报错,不做「兜底到 0」、不填默认值、不静默跳过。这条决定了你的账是「准的、异常看得见」还是「平的、问题藏起来」。
政策条文(示例):
库存数量仅允许通过追加变动行调整;禁止任何形式的手工改数。撤销与更正使用标记,不得删除历史行。库存不足时操作必须失败并提示,严禁出现负库存。
第 3 步:流程与单据——每一个动作都要能被指认
规则立完,接下来是「谁在什么情况下能动库存」。原则只有一条:每一笔库存变动都必须绑定单据和操作人。
以我们的主链路为例:
申购 → 前审批 → 报价 → 报价审批 → 采购单 → 入库(带价、生成批次)
→ 领用 / 销售申请 → 冻结 → 出库(写实领数量)→ 发票
对应到政策上,最少要立这五条:
- 入库必须有单:验收后凭采购单(或入库单)入库,入库时把采购价一起写进批次行——不是事后补价、更不是月底估价。价格和货绑死,以后行情怎么变都不漂移。
- 出库必须有单:出库数量写「实领数量」,并回写单据状态(已出库 / 部分出库)。不允许「先走货后补单」成为常态。
- 申请与执行分离:提需求的人不批、批的人不管库、管库的人不改单。
- 一次变动一条链:从出库行能查到入库批次,从入库批次能查到采购单和供应商。
- 单据状态机明确:每个状态有唯一入口和出口(谁、什么条件下、做哪个动作),不接受「状态随便改」。
第 4 步:预留(冻结)政策——高值物料的必选项
做到第 3 步,账是准的;但「准」不等于「不打架」。高值物料必须有第四步:确认使用的那一刻先冻结库存,把货留给这张单。
冻结的实现方式很重要,它不是「给原行打个标记」,而是:
- 先校验,再落行:查该批次当前可用数,够才允许冻结;不够就明确报错(「此位置没有足够库存冻结」),绝不悄悄少冻一点。
- 复制一行、数量等于本次需求:从原入库行复制批次信息(inID、价格、批号、仓库……),状态置 0,原行不动。
- 冻结行绑定归属:领用人、领用单明细。出库时只删绑定这张单的冻结行,别人的冻结碰都不碰。
这一条同时解决两个经典事故:不会超售(冻不上就是不够),也不会出现「A 的货被 B 领走、被 B 卖掉」(货和单据绑定了)。
注意一个真实的坑:冻结在实现上是「读 → 判断 → 插入」三步,不是原子操作。两个并发请求会都读到旧的可用数,各插一行,冻结总量超过入库总量,可用数量变成负数——我们实测出现过 −20(入库 20,被冻了两次共 40),两条冻结行字段完全一样、时间只差几十毫秒。修法是两道防线:后端把同一批次的冻结操作串行化(后到的请求等前一个跑完再查视图),前端禁止重复提交。如果你在制度里写了「不允许超卖」,那系统里就必须有对应的并发保护,否则这条制度是纸的。
第 5 步:例外流程——盘点、撤销、报损、拆分、转移
正常流走通了,政策的一半就成立了;剩下的一半全在例外里。每一项都要有「谁能发起、谁批准、留下什么痕迹」:
- 盘点:盘盈盘亏都走「盘点入库 / 盘点出库」两种变动行,配一个盘点标记区分「有效」与「盘点」,不要直接改数。这样盘点前后的账都能回看。
- 撤销:标记失效(不参与核算),不删除。删了就没有审计线索。
- 报损:走报损出库,记录原因和分摊;高值物料建议设金额阈值,超过阈值要审批。
- 拆分 / 组合:产生新批次(新身份),原批次失效;两份记录都要能互相指认。
- 转移(跨仓/跨人):转出只是提出,接收方确认才生效——转移过程有在途状态,不要一步到位改管理人。
第 6 步:权限政策——先写「不能做什么」
权限不只是「谁能看」。从零建政策,建议把角色划成五类,然后给每类写两张清单:可以做什么 / 不能做什么。我们的划分是:申请人、审批人、采购、仓管、管理员(再往上还有超级管理)。
立几条硬规则:
- 申请人不能审批自己的单;
- 采购不能自己管库、不能自己改入库数量;
- 仓管能执行出入库,但不能改价格、不能改单据状态;
- 转移、盘点这类敏感操作,需要接收方或上级确认;
- 管理员能配规则,但配规则的动作本身要留痕。
「不能做什么」的清单比「能做什么」更重要——前者是防线,后者只是说明书。
第 7 步:成本与报表口径——把「数据清晰」落到一句可检验的话
库存政策走到报表这一层,最容易含糊过去。建议直接定死口径:
- 库存金额 = Σ(各批次剩余数量 × 该批次入库价),随时可算,不用等盘点;
- 出库 / 销售成本按批次价格结转,能按产品、分类、组别、人、时间段拆;
- 不用「平均价」做出入库结算(除非你明确它只是管理口径,而不是成本口径);
- 采购发票与入库、采购单能相互指认(发票金额回写采购明细)——注意这是发票与单据之间的核对,不是「库存对账」:库存只有一本账,没有第二本要核。
一句话检验标准:任何一笔钱,都能指认到某一行货。
第 8 步:结余复核与例外处理——决定政策能活多久
政策上线不是终点。要让它活下来,必须有定期体检:
- 固定复核脚本:查的不是「两本账是否一致」,而是「这一本账自己有没有异常」——检查这几类:可用数量为负、冻结超过入库、批次缺价格、引用悬空(指向已删除的物料/供应商)、单边记录(有出无入);
- 差异处理流程:发现 → 定位到具体行 → 修正(用追加行,不改旧行)→ 记录原因;
- 节奏:上线首月每周跑一次,稳定后每月一次。
我们的经验是:这个层次的错误不主动找是看不见的——账面看着都平,只有拿明细重算才会露出来。所以复核不是「不信任员工」,而是政策的一部分——而且这里没有「对账」这个动作:库存只有一本账,结余是同一批流水当场算出来的,不存在两本账互相核的场景。
第 9 步:上线策略
- 先建账,后上线:账没清之前不要开新流程,否则旧错的账 + 新错的流程,永远理不清;
- 灰度:先选一个仓库 / 一个角色跑通,再铺开;
- 双轨期要短:新旧并行期间,明确「以新账为准、旧表停止写入」,拖久了必然两套账打架;
- 按角色做操作卡:一页纸,写清「你什么时候该做什么动作、点哪里、看到什么算成功」;
- 复盘:首月每周复盘异常清单,把高频问题直接改进系统(能拦住的就不要靠人记)。
一页纸政策模板(可直接抄改)
- 所有库存以批次行存在,禁止跨批次合并计数;
- 每次入库产生唯一批次身份,记录来源单据、供应商、批号、入库时间、价格、经手人;
- 库存数量只允许通过追加变动行调整,禁止手工改数;撤销与更正使用标记;
- 入库必须凭单,入库即带采购价;
- 领用 / 销售前必须先冻结;冻结不足必须失败报错;
- 出库写实领数量,并回写单据状态;
- 每一笔变动必须绑定单据与操作人;
- 严禁负库存;异常必须可见(不兜底、不填默认值、不静默跳过);
- 余额以聚合口径计算,展示「可用 / 冻结 / 实数」三个数字;
- 盘点、报损、拆分、转移均走变动行,保留历史;
- 转移需接收方确认方能生效;
- 申请、审批、采购、仓管职责分离;
- 出库成本按批次价结转;库存金额按批次价计算;
- 每月看一眼结余与异常清单,处理闭环(库存只有一本账,不设「对账」环节);
- 系统规则变更需留痕,重要规则变更需审批。
常见坑(我们真踩过的)
- 先买系统再定规则:系统只是把规则固化,规则没想清,系统帮你把混乱自动化;
- 建实体余额表:迟早对不上,且对不上的那天你不知道从哪查;
- 只做流程不做批次:流程再规范,成本也算不清、追溯也做不了;
- 忽略并发:制度写「不许超卖」,代码里却是「读—判断—写」,重复冻结一发生,可用数为负;
- 出错兜底:库存不够就按 0 处理、字段缺了就填默认值——账面平了,问题全藏起来了,这是最贵的省事;
- 权限不上心:申请人 = 审批人 = 仓管,再好的账也会被改坏;
- 拿平均价当成本:高值物料上,这是系统性算错。
一句话总结
从零建立库存管理政策,本质是四件事按顺序做:给每批货一个身份(批次)→ 把数量改成只追加的三态事件账(入库 / 冻结 / 出库,余额靠聚合)→ 每个动作绑定单据和人(先冻结再出库)→ 用结余复核和异常清单让它活下来。 规则先于系统,形状先于流程;形状对了,超售、串货、成本不清、追溯不了,都是同一个问题的不同症状,会一起消失。
关于我们:东莞妥达信息(tudait.com),做精细化库存管理(WMS)与企业管理软件 —— 国产自研、私有化部署,数据留在企业自己手里。
相关:精细化库存管理(WMS) · 常见问题 · 关于我们
更多库存管理文章:如何处理呆滞库存? · 如何协调多平台的库存和发货? · 如何实现实时动态库存管理? · 小企业做批发,进销存财务一体软件怎么选? · 小工厂仓库怎么管控? · 库存异常反映什么问题? · 库存混乱、销售数据不清晰怎么办? · 第三方仓储计费:库存管理软件怎么选? · 预测准确率 90%,为什么库存还是乱?
你的库存,卡在「管不清」还是「改不动」?
把场景(品类、批次 / 效期要求、现在怎么管)发给我们,评估后给方案与周期。