简介这份文档围绕SAP物料主数据中的物料状态Material Status展开面向正在参与SAP上线数据维护的PP、MM、QM、FICO等模块顾问及关键用户帮助理清物料状态在采购、生产、质量与财务流程中的流转逻辑。资源包内含1个doc文件压缩包约248KB以文字说明与配置表格为主便于随时查阅与对照。文档结合企业实际维护场景梳理了01已批准采购计划、02已批准生产计划、03通过质量管理、10释放用于生产和服务、99新建待修改等状态值的业务含义并说明Basic data 1、Purchasing、MRP1、Costing 1与Work scheduling等视图间状态字段的同步关系同时给出OMS4后台配置路径及各状态值对应的消息控制设定。目前已有2437人学习下载适合需要理解物料状态跨模块协作机制、排查状态变更与消息提示问题的读者参考。1. 物料状态不是“开关”是主数据治理的咽喉很多做 SAP MM 的同行第一次接触物料状态都是被业务怼出来的。采购说这个料不能买计划说这个料不能跑 MRP仓库说这个料还能收但不能发财务说这个料不能过账——你打开 MM03 一看物料主数据里那个“状态”字段填了个数字谁也说不出这个数字到底锁了哪些动作。物料状态Material Status在 SAP 里从来不是一个简单的启用/禁用开关它是一套横跨采购、生产、库存、财务过账的交叉校验矩阵。你把它当开关用它就让你在月末结账时翻车你把它当治理工具用它就能在物料生命周期里替你挡掉大量脏数据。这篇笔记面向的是正在做物料主数据治理、或者被物料状态锁单问题折腾过的 MM/SD/PP 顾问和关键用户从字段配置一路讲到跨模块排查把“这是什么、怎么配、坑在哪”讲透。2. 物料状态到底锁了什么从配置表到业务动作的映射2.1 物料状态与物料类型的本质区别刚入行的人最容易把物料状态和物料类型搞混。物料类型Material Type比如 ROH、HALB、FERT决定的是这个物料“是什么”它控制的是物料主数据本身有哪些视图、哪些字段必填、编号范围怎么走。物料状态Material Status决定的是这个物料“现在能干什么”它控制的是业务交易层面允许或禁止哪些动作。一个是身份一个是权限。在标准 SAP 里物料状态通过事务码 OMS4 维护底层落在 T141 和 T141T 两张表。T141 存的是状态码和它对应的业务事务控制标识T141T 存的是状态码的多语言描述。每个状态码背后有一组“业务事务”Business Transaction比如采购订单、采购申请、生产订单、库存移动、发票校验、成本核算等每个事务又可以设成“允许”“警告”“禁止”三种级别。这里有个关键点物料状态是跨工厂的但业务事务的锁定效果会受工厂、库存地点、移动类型等维度影响。也就是说同一个状态码在 A 工厂可能只警告在 B 工厂可能直接禁止这取决于你在配置里怎么挂。2.2 业务事务的三种控制级别与优先级OMS4 里每个业务事务的控制标识有三个值控制标识含义业务表现空允许正常执行无提示1警告弹出警告消息用户可回车继续2禁止直接报错事务终止优先级规则是禁止 警告 允许。如果同一个物料在多个维度上被设了不同级别系统取最严格的那个。比如物料主数据层面设了“警告”但工厂层面设了“禁止”最终以禁止为准。这里有个血泪经验很多顾问配完状态码之后只测了 MM01 创建没测后续交易结果上线后采购订单能建但收货时被禁止业务直接炸锅。所以配置完必须把采购、收货、发货、过账、MRP 全链路跑一遍。2.3 用 OMS4 配置一个自定义状态码的完整步骤下面以创建一个“冻结采购但允许库存移动”的状态码为例走一遍配置流程。第一步进入 OMS4点击“新条目”。第二步输入状态码比如 Z01描述填“冻结采购允许移动”。第三步在业务事务列表里找到“采购订单”和“采购申请”把控制标识设为 2禁止。第四步找到“库存移动”相关的事务保持为空允许。第五步保存。系统会提示请求号挂到传输请求上。配置完成后底层数据长这样-- 查询 T141 表看状态码 Z01 的业务事务控制 SELECT * FROM T141 WHERE MMSTA Z01; -- 查询 T141T 表看状态码描述 SELECT * FROM T141T WHERE MMSTA Z01 AND SPRAS 1;逻辑说明T141 的 MMSTA 字段就是物料状态码后面的字段对应各个业务事务的控制标识。T141T 的 SPRAS 是语言键1 代表中文。查完这两张表你就能确认配置有没有真正落库。参数说明OMS4 里业务事务的字段名和 T141 的字段名不是一一对应的比如“采购订单”在 T141 里可能是 BSTAE 或类似的字段具体要看版本。建议配置完直接用 ST05 跟踪一次业务操作看系统到底读了哪个字段比翻文档快。2.4 物料状态在物料主数据里的赋值位置状态码配好之后要赋给具体物料。路径是 MM01/MM02 的“基本数据 1”视图字段叫“物料状态”。这个字段在 MARC 表里是 MMSTA在 MARA 表里也有一个 MMSTA但两者含义不同MARA-MMSTA 是跨工厂的默认状态MARC-MMSTA 是工厂级状态。实际业务中系统会先读 MARC如果 MARC 为空再读 MARA。这里有个容易踩的坑如果你在 MM01 创建时只填了基本视图的状态没进工厂视图确认MARC-MMSTA 可能是空的导致工厂级控制失效。正确做法是创建完物料后用 MM03 进工厂视图再检查一遍。 用 ABAP 快速检查某物料在各工厂的状态码 SELECT matnr, werks, mmsta FROM marc INTO TABLE DATA(lt_marc) WHERE matnr lv_matnr. 如果 lt_marc 里 mmsta 为空说明工厂级状态没维护逻辑说明这段代码直接查 MARC 表比在 MM03 里一个个工厂点开快得多适合批量排查。参数说明lv_matnr 是物料号注意前导零SAP 内部物料号是 18 位外部输入通常要去掉前导零再补全。3. 物料状态在采购与库存场景下的实战控制3.1 采购订单创建时状态码的拦截逻辑当你在 ME21N 创建采购订单时系统会先读物料主数据的状态码然后检查 T141 里“采购订单”这个业务事务的控制标识。如果是 2禁止直接报错“物料状态不允许采购订单”。如果是 1警告弹黄灯消息用户回车可以继续。但这里有个细节采购订单的行项目里物料号是从采购信息记录或物料主数据带出来的状态检查发生在保存前还是输入物料号时答案是输入物料号回车时就会触发检查。所以如果你在 ME21N 里输入物料号后没报错但保存时报错那大概率不是物料状态的问题而是别的校验比如供应商冻结、采购组权限。我一般会建议客户在配置状态码时对“采购订单”和“采购申请”分别设控制。因为有些业务场景是“可以申请但不能下单”这时候采购申请设允许、采购订单设禁止就能实现。3.2 库存移动时 MIGO 的状态校验与移动类型关联MIGO 里的状态校验比采购订单复杂因为库存移动涉及移动类型。物料状态对库存移动的控制不是简单的一刀切而是和移动类型组合生效。比如状态码 Z01 禁止“收货”但允许“发货”那么 101 收货会被拦201 发货能过。配置层面OMS4 里“库存移动”这个业务事务其实是一组包括收货、发货、转储、盘点等。你需要逐个确认。有些版本里库存移动的控制标识在 T141 里是分开的字段比如 WEBEF收货和 WEAUS发货。# 用 MIGO 测试状态码是否生效的快速方法 # 1. 用 MB52 查该物料当前库存 # 2. 用 MIGO 做一笔 101 收货看是否报错 # 3. 如果报错用 ST05 跟踪看读的是 T141 哪个字段 # 4. 对比 OMS4 配置确认字段映射逻辑说明ST05 跟踪是排查状态码问题的后悔药因为 SAP 版本差异大文档不一定准跟踪一次比查半天资料快。参数说明ST05 跟踪时记得勾选“SQL 跟踪”否则看不到底层表读取。3.3 用 MIGO 和 MB52 验证状态码是否生效配置完状态码别急着上线先做一轮验证。验证清单如下验证项事务码预期结果采购申请创建ME51N按配置允许/警告/禁止采购订单创建ME21N按配置允许/警告/禁止收货MIGO 101按配置允许/警告/禁止发货MIGO 201按配置允许/警告/禁止库存查询MB52不受状态影响始终可查MRP 运行MD01按配置允许/警告/禁止注意MB52 和 MM03 这类查询事务通常不受物料状态控制因为状态控制的是“交易”不是“查询”。如果你发现查询也被锁了那大概率是权限角色的问题不是物料状态。3.4 状态码与采购信息记录的优先级冲突这是一个很少人讲但实际会遇到的坑如果物料主数据状态允许采购但采购信息记录里设了“冻结”标识系统以哪个为准答案是采购信息记录的冻结优先级更高。因为采购信息记录是采购层面的独立控制物料状态是主数据层面的控制两者是“与”关系任何一个禁止都会拦。所以排查采购订单报错时别只看物料状态还要看采购信息记录、供应商主数据、采购组权限。我一般会按这个顺序查物料状态 → 采购信息记录 → 供应商冻结 → 权限。4. 物料状态与 MRP、财务过账的交叉影响4.1 MRP 运行时状态码如何影响需求计算MRP 运行MD01/MD02/MD03时系统会读物料状态里“MRP”这个业务事务的控制标识。如果设为禁止该物料不参与 MRP 运算不会产生计划订单和采购申请。这个控制非常有用比如对于即将淘汰的物料你可以设一个“停止 MRP”的状态避免继续产生需求。但这里有个坑MRP 控制标识在 OMS4 里可能叫“需求计划”或“MRP”不同版本翻译不一样。而且 MRP 运行是后台作业报错信息不会弹窗只会写进 MRP 清单。所以如果你发现某个物料突然不跑 MRP 了先查物料状态再查 MRP 清单里的消息。 检查某物料是否因状态码被 MRP 排除 SELECT matnr, werks, mmsta, dismm FROM marc INTO TABLE DATA(lt_check) WHERE matnr lv_matnr. dismm 是 MRP 类型如果为空或 ND本身就不跑 MRP mmsta 是状态码需要结合 T141 判断 MRP 控制标识逻辑说明这段代码同时查了状态码和 MRP 类型因为有些物料不跑 MRP 是 MRP 类型设成了 ND不计划不一定是状态码的问题。参数说明dismm 字段在 MARC 表里常见值有 PDMRP、ND不计划、VB再订货点等。4.2 财务过账时状态码对移动类型的影响财务过账层面物料状态主要影响的是“发票校验”和“成本核算”。比如状态码禁止“发票校验”那么 MIRO 时该物料的采购订单无法做发票校验。这个控制通常用于质量冻结或财务冻结场景。但要注意物料状态对财务过账的控制和 MM 层面的库存移动控制是独立的。也就是说你可以允许收货但禁止发票校验这在“货到票未到”的场景下很常见。4.3 跨模块排查状态码报错时先查哪张表当业务报错“物料状态不允许 XX 操作”时排查顺序建议如下用 MM03 查物料主数据基本视图和工厂视图的状态码。用 OMS4 查该状态码对应业务事务的控制标识。用 ST05 跟踪报错事务确认系统读的是 T141 哪个字段。如果配置没问题查采购信息记录、供应商主数据、权限角色。如果还找不到查用户出口或 BADI 是否有自定义校验。这个顺序能覆盖 90% 的状态码报错场景。剩下的 10% 通常是版本差异或自定义增强需要看代码。5. 物料状态配置与使用的避坑清单5.1 坑一状态码改了但业务没生效现象在 OMS4 里把某个业务事务从允许改成禁止保存后业务操作仍然能过。原因OMS4 的配置修改后需要清缓存或者重新登录才生效。SAP 的配置表有缓冲机制特别是 T141 这种频繁读取的表。解决用 $SYNC 或 /$SYNC 清缓存或者让用户重新登录。如果还不行用 ST05 跟踪确认读的是不是最新配置。最彻底的方法是重启应用服务器但生产环境慎用。5.2 坑二工厂级状态和跨工厂状态冲突现象MARA-MMSTA 设了允许MARC-MMSTA 设了禁止业务报错但用户说“基本视图里明明是允许的”。原因系统优先读 MARC-MMSTAMARA-MMSTA 只是默认值。用户只看了基本视图没看工厂视图。解决用 MM03 进工厂视图确认或者直接查 MARC 表。批量排查时用 SE16N 或 ABAP 查询。5.3 坑三状态码传输后目标系统没同步现象开发机配了状态码传输到测试机后业务报错“状态码不存在”。原因OMS4 的配置挂在传输请求里但 T141T 的描述文本可能没带过去或者传输顺序不对。解决检查传输请求里是否包含 T141 和 T141T 两张表的数据。用 SE01 看传输日志确认没有报错。如果描述文本丢了在目标系统手动补一下。5.4 坑四MRP 控制标识设了禁止但 MRP 还在跑现象OMS4 里 MRP 设了禁止但 MD01 跑完还是产生了计划订单。原因MRP 运行读的是 MARC 里的 MRP 类型和状态码但如果你用的是 MRP LiveMD01 的新版本控制逻辑可能不同。另外已经存在的计划订单不会因为状态码变更而自动删除。解决先确认 MRP 类型不是 ND再确认状态码的 MRP 控制标识确实设了禁止。已经产生的计划订单需要手动删除或重跑 MRP。5.5 坑五状态码被权限角色覆盖现象物料状态设了禁止采购但某个用户仍然能创建采购订单。原因用户的权限角色里可能有绕过物料状态检查的权限对象比如 M_MATE_STA 的某个值设成了允许。解决用 SU53 查权限检查结果或者用 ST01 跟踪权限。确认权限角色里 M_MATE_STA 的配置必要时收紧。6. 用状态码做物料生命周期治理的进阶技巧物料状态真正有价值的用法不是单个物料的手工设置而是结合物料生命周期做批量治理。我一般会建议客户按“新品导入 → 正常使用 → 逐步淘汰 → 完全冻结”四个阶段设计状态码每个阶段对应不同的业务事务控制组合。比如新品导入阶段状态码允许采购和收货但禁止 MRP 和成本核算避免新品还没确认就产生需求。正常使用阶段全开。逐步淘汰阶段禁止采购和 MRP但允许库存移动和发货让现有库存慢慢消耗。完全冻结阶段禁止所有业务事务只保留查询。批量赋值可以用 MM17 或者 LSMW但更高效的方式是写一个简单的 ABAP 报表按物料类型、采购组、创建日期等条件批量更新 MARC-MMSTA。下面是一个批量更新的核心逻辑 批量更新物料状态码的 ABAP 核心逻辑 DATA: lt_marc TYPE TABLE OF marc, ls_marc TYPE marc. 1. 按条件取数 SELECT matnr werks mmsta FROM marc INTO TABLE lt_marc WHERE werks p_werks AND matnr IN s_matnr. 2. 循环更新 LOOP AT lt_marc INTO ls_marc. ls_marc-mmsta p_newsta. p_newsta 是目标状态码 MODIFY marc FROM ls_marc. IF sy-subrc 0. WRITE: / ls_marc-matnr, 更新成功. ELSE. WRITE: / ls_marc-matnr, 更新失败. ENDIF. ENDLOOP. 3. 提交 COMMIT WORK.逻辑说明这段代码直接更新 MARC 表绕过 MM02 的前端校验速度快但风险高。参数说明p_werks 是工厂s_matnr 是物料号选择范围p_newsta 是目标状态码。注意直接更新数据库表不会触发物料主数据的变更凭证如果审计要求严格建议用 BAPI_MATERIAL_SAVEDATA 代替。验证方法更新后用 MM03 抽查几个物料确认状态码已变。再用 MIGO 或 ME21N 测试业务事务是否按预期控制。如果发现异常用 ST05 跟踪确认读的是最新值。我自己的习惯是任何批量更新前先用 SE16N 把要更新的物料清单导出来备份更新后再导一次对比。这个后悔药成本很低但关键时刻能救命。另外状态码的变更一定要走传输请求别在生产环境直接改否则开发机和测试机的配置会不一致下次传输时互相覆盖。希望帮到你。本文还有配套的精品资源点击获取