做Odoo实施这些年,我有个特别深的体会:十个库存项目里八个出问题,根源往往不在库存模块本身,而是位置(Location)没建模好。位置管理分两件大事,一件是区分物理位置和虚拟位置——也就是搞清楚“货到底放在仓库哪个货架上”和“这批货在账务上处于什么状态”;另一件是围绕位置把入库、出库、存储、补货这一整套策略设置配顺。这篇全指南就基于Odoo 18展开,把位置分类逻辑和策略配置的来龙去脉讲透,适合正在实施Odoo的顾问、企业IT、仓库负责人,以及刚接触Odoo库存模块打算自学的开发者。我尽量不讲废话,全是实操里验证过的东西。
1. 位置管理没搞懂,库存账迟早要乱——先从位置的本质说起
1.1 位置到底是什么:库存移动链上的节点
Odoo的库存模块里没有传统ERP那种“库存总表”,货物流转靠的全是库存移动(Stock Move)。每一笔移动都有一条“源位置 → 目标位置”的记录:采购收货是“供应商位置 → 仓库内部位置”,销售发货是“仓库内部位置 → 客户位置”,生产领料是“仓库位置 → 生产位置”。所以位置在Odoo里,本质上不是一张静态标签,而是库存移动链上的节点。
把这套机制比作交通系统,位置就是站点,库存移动就是跑在站与站之间的车。你可以在任意两个站点之间发车,但每辆车必须明确“从哪来、到哪去”,否则系统根本不知道怎么记账。这也是Odoo和很多传统ERP“货品存量表一刀切”思路的最大区别——它不关心一个产品“总量是多少”,更关心“这批货现在处于什么状态、到了哪个环节”。比方说你有一批原料正在海上漂着、一批成品已经发给客户但还没确认签收、一批次品等着报废,这三批货在物理上都不在你仓库里,但它们的账务状态完全不同。Odoo用位置来承载这些状态,所以在做库存追溯时,你永远能回答“这批货是从哪来、到哪去、现在在哪”。
在这个体系下,位置不只是名字,它还带有类型属性。Odoo用“内部位置(Internal Location)”这个复选框来区分物理货位和虚拟节点:勾选上的,代表公司自己可控的物理仓库空间;没勾选的,就是虚拟位置,用于表达业务流转的账务节点。很多人第一次建位置就卡在这里,我慢慢往下拆。
1.2 物理位置与虚拟位置:一张表看清本质区别
很多新手一开始会被这俩概念绕晕。物理位置好理解,仓库里的货架、库位、货柜、托盘位,占了实体空间;虚拟位置就不太好懂,因为它看不见、摸不着,只在单据和报表里存在。我通常用下面这张表做区分,客户看完基本都能明白:
| 对比维度 | 物理位置(内部位置) | 虚拟位置 |
|---|---|---|
| 是否占用实体空间 | 占用,有货架、库位、托盘等 | 不占用,只是一个逻辑节点 |
| 是否勾选“内部位置”选项 | 必须勾选 | 不勾选 |
| 库存归属 | 计入公司实有可用库存 | 不计入公司可用库存,作为在途、已交付等状态载体 |
| 典型用途 | 收货暂存区、原料仓、成品仓、质检冻结区 | 供应商位置、客户位置、生产位置、库存损失位置、中转位置 |
| 可操作性 | 支持扫码、容量校验、物理盘点 | 主要是账务流转记录,不可扫码上架 |
只看表格可能还不够直观,我举一个真实项目里遇到的场景。某家公司做跨境贸易,采购的大批货在运输途中,财务想看“在途库存到底有多少钱”。如果没把供应商位置理解成虚拟节点,这批在途货很可能被操作员随手录入到某个内部仓库,账面库存立刻虚高,财务结账对不上。而正确理解是:供应商位置这个虚拟节点专门用来挂“已采购、未收货”的库存,货物只有扫码进了公司内部位置才算真正入库。这个区分做到位了,在途库存报表、资金占用分析、采购到货追踪就都顺了。
还有一个细节值得注意:虚拟位置里的数量虽然不计入公司可用库存,但它会出现在“预计库存(Forecast)”里。预计库存的计算逻辑是在手库存加上未来的入库移动、减去未来的出库移动。所以虚拟位置的存在,恰恰让“预计库存”变得完整——采购在途会让你看到未来能到多少货,销售已发但未确认会让你看到未来库存会消耗多少。
1.3 从根位置看Odoo内置的位置体系
打开Odoo的位置列表(设置 → 库存 → 位置),默认会看到一组根位置,它们就是Odoo库存模块自带的“虚拟位置大本营”。我把它们挨个说一下:
- 物理位置(Physical Locations):所有仓库、库区、货架的顶层根节点,本身是一个父级视图节点。
- 供应商位置(Vendor Location):采购收货的源头,挂在它下面的库存代表“在途采购”。
- 客户位置(Customer Location):销售发货的终点,挂在它下面的库存代表“已交付客户”。
- 生产位置(Production Location):生产领料和成品入库的账务缓冲,代表“已进入制造环节”。
- 库存损失位置(Inventory Loss Location):盘点差异、报废、损耗的兜底位置。
- 中转位置(Transit Locations):跨仓库调拨、多步骤收发货时的在途缓冲。
这些根位置不需要自己建,安装库存模块后系统就带上了。创建新仓库时,Odoo会自动在“物理位置”根节点下生成对应仓库的位置树,比如常见的WH/Stock;而供应商、客户、生产、库存损失这些虚拟位置,则在采购、销售、制造模块跑流程时自动参与。
理解这套根位置体系,对后续做追溯和报表分析特别重要。因为任何一笔库存增减,最终都能归到某一个根位置之下,数据不会出现“无家可归”的情况。很多上线后库存对不上的项目,排查到最后都会发现,问题就出在有人绕过这套体系,随手建了一堆没有父位置、没有类型的“野位置”。
2. 物理位置建模实操:仓库、区域、货架、库位的落地步骤
2.1 先画一张仓库地图,再建位置树
物理位置建模这步,最忌讳的就是打开Odoo直接新建位置,边建边想。我在项目里带客户做的第一件事,永远是先画一张仓库物理地图:哪个区域放原材料,哪个区域放成品,哪个通道是收货暂存区,哪块角落留给待报废品。画完之后,再把这些区域映射成Odoo里的位置树。
一个典型制造业仓库的位置树大致长这样:
WH(仓库根,父级) └── WH/Stock(库存内部位置根) ├── WH/Stock/Raw(原材料区) │ ├── WH/Stock/Raw/A(A类原材料货架) │ └── WH/Stock/Raw/B(B类原材料货架) ├── WH/Stock/Finish(成品区) ├── WH/Stock/Blocked(质检冻结/待处理区) └── WH/Stock/Scrap(待报废区)层级的核心原则是:叶子节点用来放货,父节点用来汇总。Odoo计算某个位置的库存时,会自动把其所有子位置的数量汇总上来,所以你只需要在末端货位上做入库、出库、盘点,上层节点自然更新。这个设计极大的简化了日常操作,操作员不需要去改父级数据,系统自动汇总。
画完地图之后,还有两件事要一并定下来。一件是位置编码规则。我建议用一个统一的编码格式,比如“仓库编码/区域/通道/货架/层”,像WH/A/03/02/05这种,比“A区三通道二号货架五层”在这种单据和扫码界面上直观得多。另一件是层级深度。理论上Odoo支持无限层级,但实际实施我不建议超过四层:仓库 → 区域 → 货架 → 库位。层级太深,操作员扫码拣货要多跳好几级,查询报表也会被拖慢,得不偿失。
2.2 创建内部位置的关键字段与层级技巧
新建物理位置时,在位置表单里重点要看的字段其实不多,但每一个都别漏:
- 位置名称:按前面定的编码规则填,别用自由文本。
- 内部位置:必须勾选。勾了才代表公司内部物理库存,才能在入库单、发货单里作为正式库位被选择。
- 父位置:选择上一级。位置类型会从父位置继承,叶子节点只要选对父级,内部位置选项一般就不用重复纠结。
- 允许的产品 / 允许的包装:如果某个位置只放特定产品或特定规格包装,可以在这里限定,防止操作员乱放。
- 位置备注:把存放规则、库位尺寸、是否限重等信息写进去,给操作员当操作提示。
这里要提醒一下,父位置的选择是个容易出错但又很关键的环节。很多人图方便,把所有位置都直接挂在仓库跟节点下面,结果位置列表一千多行,找谁都费劲。正确的做法是先建好“区域”这一层(比如原料区、成品区、冻结区),再在区域下面建货架和库位。这样不仅树形结构清楚,后续做补货规则、存储策略、盘点分组时,也可以直接按区域统一配置。
另外一个实操细节:如果公司有多个仓库,建议把仓库编码放进位置编码第一位,比如WH01/Stock/Raw和WH02/Stock/Raw。这样一张报表看多仓数据时,位置能直接反映出属于哪个仓库,不用再额外关联仓库字段。
2.3 容量、条码、允许的产品:位置定义的高级属性
别小看物理位置表单里的容量相关设置。很多人上线时直接忽略,等到仓库里托盘放不下、收货时才发现问题。Odoo 18里,位置可以设置最大重量、最大体积等容量约束,配合“允许的产品”“允许的包装类型”一起用,系统在做位置分配时就能提前校验,避免货到了才发现放不下。
我见过一个仓库,收货时操作员凭经验找位置,经常找到一半发现货架满了,又推着托盘满仓库找空位。后来我帮他给每个位置设置了最大托盘数和最大重量,配合入库规则让系统自动推荐位置,收货效率提升了大概三成。这不是什么高级功能,只是位置属性配得细了一点。
还建议在位置表单里填上条形码,然后打印位置标签贴在货架侧面。这是移动端扫码拣货的基础。仓库同事拿出扫码枪,先扫位置条码,再扫产品条码,库存转移就完成了,基本不会出现录入错位。后续要做盘点、调拨、拣货,扫码效率比手工选择位置高出一大截。
还有一个容易被忽略的细节:仓库表单里有“收货步骤”和“发货步骤”的设置。如果收货设为2步,系统会自动创建WH/Input这类收货暂存内部位置;设为3步还会再多一个中转站。这些自动创建的位置属于内部位置,但千万不要把它们当成正式库位来放长期库存——它们只是流程中间暂存节点,货物一到就得尽快移入正式库位。如果不约定好这个操作习惯,很可能会出现货物永远堆在WH/Input不挪走的“僵尸库存”。
3. 虚拟位置分类与应用场景:供应商、客户、生产、报废、中转
3.1 供应商位置与客户位置:库存归属性流转的起点和终点
采购订单确认后,从“供应商位置”到仓库内部位置的入库移动会立即生成,但此时它只是“预计库存”;货物真正扫码入库后,库存数量才会落到内部物理位置。这带来一个好处:在途采购的货有一个明确的账务归属地,不会和现有库存混在一起,财务可以通过报表清楚看到“在途库存”的金额,对资金占用一目了然。
客户位置同理。销售发货完成后,库存从内部位置转移到了“客户位置”,在报表上代表这批货的所有权已经交给客户。很多公司退货流程乱成一团,根源就是没理解这个位置的意义:退货时,正确的操作是做一笔“客户位置 → 内部位置”的库存移动,把库存加回来。如果直接把客户位置当垃圾桶,随便调整数量,账和实物永远对不上。
这里我想多讲一个实际业务例子。某家电商代运营公司,仓库每天发货量很大,退货也很多。上线前他们总抱怨Odoo退货流程难用,我一看,原来他们把所有退货都直接做成了“报废”,存货越退越少,月底账实差异大得吓人。后来把退货流程改成“客户位置 → 质检位置 → 正式库位”三步走,账一下就对上了。虚拟位置用得好,不只是技术正确,还能直接挽回利润。
3.2 生产位置与库存损失位置:制造和盘点的两个“账务缓冲”
生产位置可能是最被误解的虚拟位置。生产领料时,系统把原料从“内部位置 → 生产位置”,代表材料已经交给车间;生产完成后再把产成品从“生产位置 → 内部位置”。如果只看原料库存,会觉得原料“消失”了,其实它是在制造过程中转化了形态。Odoo用这个位置来衔接原料到产成品的转换账务,使得一张生产订单的全过程都有据可查。
在企业版里,生产位置通常还会跟制造模块的“完工入库”联动。原材料消耗多少、成品产了多少、中间损耗多少,系统都会在移动记录里留下痕迹。做成本核算时,这批数据就是最底层的依据。
库存损失位置则是所有盘点、报废操作的“兜底”选项。做库存盘点,如果发现账实差异,盘点结算后Odoo会自动把差额转到“库存损失”这个虚拟位置。报废操作也一样,系统会把废品从正式库存移到库存损失位置。这个位置记录的是企业实际发生的损耗和盘盈亏,是财务做存货跌价、报损审批的基础数据。所以一般情况下,这个位置不允许手动改数量,否则审计上说不清楚。
有一点要特别提醒:库存损失位置和生产位置都是虚拟位置,不要给它们建“子位置”,也不要尝试在里面放物理货物。它们存在的意义就是让“不知道归哪”的库存有一个合法的账务归宿,而不是让你把货物真的丢在某个角落。
3.3 中转位置与多步骤流程:让在途库存变得可见
当启用多仓库调拨或两步/三步收发货流程时,Odoo会创建“中转位置”。比如从上海仓调货到广州仓,移动记录会是“上海仓库存 → 中转位置(在途)→ 广州仓库存”。中转位置里的货不物理存在于任何一个仓库,但系统账上能明确看到“正在路上的库存”到底有多少。
中转位置是虚拟位置里最容易被忽视、也最能体现Odoo追溯能力的一个。因为在途货物如果出现问题,你可以直接在系统里看到这批货停留在哪个中转节点、停留了多久,而不是像表格管理那样“发出去就消失了”。尤其是那些经常做跨仓调拨、门店配货的公司,中转位置做好了,供应链计划和库存分配会轻松很多。
实操建议:多仓公司务必在仓库设置里启用中转位置功能,并且养成在调拨单上记录确认时间、预计到货时间的习惯。这笔在途库存数据,对后续做采购计划、销售承诺、缺货预警都非常有价值。
还有一个常见用法是把中转位置和“多步骤收发货”结合。比如发货设成3步:库位拣货 → 发货区打包 → 中转位置 → 客户位置。每一步都是一个独立的位置节点,仓库的每一个动作都能被看得很清楚。如果有一步一直没完成,说明货卡在了某个环节,管理上可以立刻定位责任。这就是虚拟位置在流程管理上的真正价值。
4. 策略设置的底层逻辑与实战配置
4.1 入库规则(Putaway):让货物自动找到自己的“家”
入库规则(Putaway Rules)是位置策略里的第一个大件。它解决的核心问题是:货物在收货时,系统应该自动决定把它放到哪个位置,而不是靠操作员在界面上手选。手选一多,就会出现放错货架、混放、账实不符。
Putaway规则主要由几个条件构成:产品类别、源位置(通常来自供应商位置或生产位置)、目标操作类型(收货、生产入库等)、以及最终目标位置。规则按优先级顺序匹配,不满足当前规则就尝试下一条,全部不满足时回落到默认位置。
举一个实际例子。某汽车零配件分销商,把“标准件”这个产品类别设为入库到WH/Stock/Raw/A,把“超大件”设为入库到WH/Stock/Raw/B。收货时系统自动检查产品类别,把货物绑定到正确的货架位置。操作员根本不用想货该放哪,扫码确认即可。这样既提高了收货效率,也保证了库位的稳定性。
落地的时候有几个细节值得注意:
- 规则匹配顺序很重要,越具体的规则放越前面,否则会被宽泛规则吞掉。比如先写“标准件”,再写“所有产品”兜底。
- 规则目标位置可以直接指向“父位置”,让系统在其子位置中自动寻找可用库位。
- 同一产品有多种入库来源(采购、生产、退货),需要分别建规则,不要指望一条规则通吃所有业务。
4.2 出库移除策略:FIFO/LIFO/FEFO怎么选
出库移除策略(Removal Strategy)解决的是另一个方向的问题:同一个货位上有多批次货物时,拣货时先出哪一批。Odoo 18内置三种主流策略:
| 策略 | 逻辑 | 适用场景 |
|---|---|---|
| FIFO(先进先出) | 先入库的批次先出 | 大多数无保质期要求的工业品、品牌商品 |
| LIFO(后进先出) | 后入库的批次先出 | 少数特定行业,比如某些金属材料价格波动管理 |
| FEFO(先到期先出) | 按有效期先后出库 | 食品、医药、化妆品等有保质期要求的品类 |
这里有两个容易踩的坑。第一个坑是FEFO只对启用了到期日期跟踪的产品有意义。如果产品没启用有效期,FEFO等于没设。所以在设置策略前,先检查产品主数据里的跟踪属性(批次/序列号 + 到期日期)是否已配对。否则你配了半天策略,实操时系统还是按原来的顺序出库。第二个坑是FIFO/LIFO是全局默认策略,但某些产品可能需要单独覆盖。比如同一个仓库里常规件用FIFO,临期促销品想强制用FEFO,这时不要直接改全局设置,而是在产品或产品类别上单独指定移除策略,全局配置保持相对保守。
给一个我常用的配置步骤:先在库存设置里把默认移除策略设为FIFO;再把带保质期的产品类别逐个改成FEFO;最后做几单模拟出库,确认临期批次确实被优先拣出。这样可以兼顾常规品和保质期敏感品。
4.3 Odoo 18存储策略:按编码、ABC、包装方式自动分库位
如果你用的是支持新仓储策略的Odoo 18版本,还能用到“存储类别(Storage Category)和存储策略(Storage Strategy)”这套相对较新的能力。它比Putaway规则更进一步:Putaway规则主要靠源位置和目标操作类型决定放哪,而存储策略会结合产品属性、包装方式、库存周转特征来动态选择库位。
常见的业务设计有几种:
- 按产品编码区间分库位:编码A开头走A区,B开头走B区,适合SKU多且编码有规律的分销商。
- 按ABC分析结果分库位:高周转的A类货放在离拣货口最近、最顺手的通道;低周转的C类放高层或偏远通道。
- 按包装类型分库位:整托盘件放低位货架,拆零件放拣货区,避免每天为了几件小货翻大托盘。
- 按特殊存储条件分库位:冷藏、防爆、危化品自动分配到特定区域。
这套策略的配置逻辑大致是:创建存储类别,定义这个类别接纳哪些产品匹配条件;给每个存储类别配置可用的物理位置列表和容量限制;入库时系统按策略优先级和容量余量自动推荐位置。
这里要特别提醒一句:存储策略在部分版本里属于额外付费能力,社区版默认是没有的。如果你用的是社区版,不必硬套这个概念,用Putaway规则加容量约束也能实现80%的自动化分库位效果。重要的是先把“哪类货进哪个区域”的业务规则定清楚,工具只是帮你落地。
4.4 补货规则:安全库存与内部调拨的联动
位置策略里的最后一块拼图是补货规则(Reordering Rules)。它解决的是“库存低于安全线时,系统什么时候触发补货、补多少”的问题。补货规则的核心指标就两个:最低库存(触发点)和最高库存(目标点)。当某个位置的预计库存跌破最低值,系统会自动生成补货建议。
在Odoo 18里,补货规则可以结合位置做“内部补货”。比如分店仓缺货,总仓自动生成一张内部调拨单,从总仓补货到分店。这时补货规则里的“位置”字段指定补货的目标位置,需求来源则是分店的实际销售和预测需求。这套机制的底层逻辑就是VMI(供应商管理库存)和看板补货在ERP里的落地,只是用位置把物理仓库和逻辑需求连接起来了。
我在项目里常用的配置思路是:先把安全库存测算准,按过去三个月的日均出库量乘以安全天数来定最低库存;再按采购或生产的提前期算出补货批量,用“最低库存 + 一个提前期消耗量”来定最高库存。测不准的时候宁可保守一点,多补几单总比断货把销售坑了强。
补货规则还有一个容易被忽略的联动:如果公司在多仓库之间做调拨,一定要明确“总仓补货”和“分店采购”的边界。否则总仓缺货时,分店会同时触发采购订单和内部调拨,造成重复补货。这个场景下,补货规则里的供应来源字段就很重要,先把来源配置清楚再定数量。
5. 常见坑位与排查思路
5.1 虚拟位置被当成内部位置勾选,报表直接虚高
这个问题在开头案例里说过一次,但因为太典型,必须再强调一遍。新建位置时,很多人看到“内部位置”复选框就顺手打勾,结果把供应商位置、客户位置这种虚拟节点全勾成了内部位置。后果就是采购在途货、已发货货都被算进公司可用库存,报表虚高一大截,财务和销售对账怎么都对不上。
排查方法其实很简单:打开库存报表,如果发现某个产品数量异常偏高,切到“位置”视图,看看高位数量是不是来自那些疑似虚拟位置。点进去看位置表单,“内部位置”如果是勾选状态,而实际操作上又不可能扫码到这个货,那就该取消勾选并做一次库存修正。记住一个原则:凡是“无法扫码、无法实际触碰”的位置,全都不该勾内部位置。
5.2 删除被引用的位置报错:归档才是正路
位置一旦被任何库存移动、单据引用过,就不能直接删除,这是Odoo的保护机制。很多新手遇到这个报错会很慌,以为系统坏了。其实正确做法是“归档(Archive)”,而不是删除。归档后位置不再出现在常规选择列表里,但历史单据和追溯记录依然完整。
归档的另一个好处是,你可以保留完整的仓库结构变化历史。哪一天要查“这批货之前到底放在哪个旧货架”,归档位置里依然能查到。所以,能归档的不删除,这是运营了三年以上仓库的基本素养。如果你发现某个位置被大量历史单据引用,千万别为了界面干净硬删,先把历史数据看明白了再说。
5.3 存储策略和入库规则冲突时,先测试再上线
当Putaway入库规则和存储策略同时启用时,系统内部有优先级和冲突处理逻辑,但业务上很容易出现“规则定义了,货还是放错了”的假象。实际上,这种情况十有八九是上线前测试不充分导致的——仓库同事实际看到的推荐位置和预期不一致。
我的经验是上线前必须做三组端到端测试。第一组测常规产品,确认走正确的指定库位;第二组测边界产品,比如超大件、临期品、特殊存储条件的货,确认能落到备用位置;第三组测容量溢出场景,确认目标位置放不下时会给出正确提示,而不是静默放到别处。三组测试跑完再培训仓库同事,基本能避开九成上线初期的位置混乱。测试数据建议单独做一个测试仓库或测试位置树,别在正式数据上造,不然后面清理起来很痛苦。
5.4 质检区没建,不合格品混入可用库存
最后一个坑是业务层面的。很多公司上线Odoo时只建了原料仓、成品仓,没建质检冻结库位。来料不合格时只能先把货放一边,结果仓库同事随手把这批货扫进了可用库位。等到仓库拣货发货,这批不合格品就被当成正常品发给了客户,出了客诉才回头查。
正确的做法是在内部位置树里专门建一个“质检冻结/待处理区”,比如WH/Stock/Blocked,并配合质量模块给相关产品设置来料检验控制点。收货后先入质检区,质检通过后再移入正式库位,不合格的移到报废区或做退货处理。这一步实施阶段看起来只多花了十分钟配置,后面能省下无数个客诉电话和退货成本。
最后说两句
位置管理这件事,听起来只是ERP里的基础配置,但它牵一发动全身。我做了几年库存模块实施,最大的感受是:位置建模的成熟度,直接决定库存项目的天花板。物理位置做细了,仓库效率能起来;虚拟位置理清了,财务账能对得上;策略配顺了,操作员才能少做那么多“手工指定”。
如果你正在筹备或刚上线Odoo 18的仓库模块,我建议不要跳过位置这块。先花一个下午把仓库地图画出来,把虚拟位置和物理位置的边界划清楚,再逐条把Putaway规则、移除策略、存储策略、补货规则配上。后面维护起来,你会感谢当初这个决定。