ERP与MES批处理接口设计:共享目录、排他控制与去重实践

简介:《MES 接口设计说明书》面向参与 SAP R/3 与制造执行系统(MES)集成实施的顾问、开发人员及项目原型搭建者,围绕 MELEBUS-BMAS 模板的 MES 接口追加程序说明展开,重点解决制造指图数据抽取与实绩数据回写之间的接口设计问题。压缩包共 1 个 doc 文件,大小约 178KB,内容以接口设计文档为主,便于直接查阅和归档。文档涵盖系统目的与适用前提、制造指图抽取接口、实绩数据计上接口、R/3 与 MES 间排他控制、接口文件一览与规格,以及 ZMAF001、ZMAF005 等程序规格和参数设定,并配有业务流程图辅助理解。已有 2668 人学习,适合需要梳理 R/3-MES 接口边界、文件字段与批处理逻辑的读者作为原型设计和实施参考。

1.

很多团队一提到 MES 接口,第一反应是上消息队列、API 网关、中间件。手上这份说明书走的却是另一条路:共享目录 + 文本文件 + 管理文件锁,靠批处理每天跑一到两回。它是一份经典 ERP 批处理体系与 MES 之间的接口附加程序设计说明,把制造指图抽取、实绩数据计上两条链路、接口文件格式、跨系统排他控制、ZMAF001 与 ZMAF005 两个附加程序以及变体参数全部写死。适合两类人:正在做 ERP-MES 对接、想要一份能照着搭骨架的 MES 接口规范蓝本的从业者;以及接手老系统、想弄明白「为什么它不用 API、为什么它只跑 1-2 次」的维护者。读它的正确姿势是把它当成一份可以逐条复现的接口约定,不能只当文档走马观花。

2. 双接口的业务边界:抽取与计上各卡在哪

整条链路被切成两半,一半是 ERP 往 MES 推,叫制造指图抽取;一半是 MES 往 ERP 回,叫实绩数据计上。两条链路各有自己的触发条件、文件集合和管理文件,边界划得很清楚。先把这条边界讲透,后面看文件格式和程序才有落点,否则很容易把两个方向的排他逻辑混在一起,写出来的接口测试用例都是错的。

2.1 制造指图抽取接口:四个抽取条件与 SEND 标志

制造指图抽取干的事很单一:把 ERP 里已经发行、还没做完的指图头部信息和构成品目信息抽出来,写到接口文件里。但「哪些指图该抽」这件事,说明书叠了四层过滤条件,任何一个不满足都不会出现在文件里。

第一层是日期窗口,着手日必须落在参数文件指定的日期范围内,用「日数后以前」的写法表达,也就是今天往后 N 天以内要开工的指图才抽。第二层是系统状态,必须是已发行,且未完成、未部分完成。第三层是有效性,已取消的指图不抽。第四层是抽取管理方式,二选一。

这里有一处设计值得借鉴:抽取管理方式做成了可切换的。

管理方式判断依据适用场景
发送日志文件重复检查发送日志里没有该指图记录,即视为未发送首次接入、还没有在 ERP 里维护用户状态的场景
指图用户状态 SEND指图的用户状态 SEND 未 ON长期运行、希望状态可视、可人工干预的场景

选第一种,系统不需要在 ERP 里写任何状态,代价是每次都要扫日志文件,日志本身成了状态源,一旦日志被清理或损坏,判断就不可靠。选第二种,抽取成功后在 ERP 侧把指图的用户状态 SEND 置 ON,状态直接挂在业务对象上,谁都能在指图里看到,代价是需要额外的状态维护约定。实操上我更倾向第二种,原因很直接:日志对现场是黑匣子,指图是业务对象,出问题时你能查的东西完全不是一个量级。

抽取动作本身的执行顺序也值得注意。程序先按条件筛数据,然后写文件,文件存在就追加,不存在就新建后追加,不做覆盖。这个设计决定了后面读侧必须自己处理重复和清理,也决定了抽取侧永远不需要「先删后写」这种危险操作。抽取期间用指图处理管理文件做排他,MES 侧在跑的时候,抽取直接跳过不执行。抽取正常完成后才置 SEND。注意这个顺序:先写文件、再置状态,中途失败的话状态不会置上,下一轮会重抽,这是有意为之的补偿。

2.2 实绩数据计上接口:两种实绩类型与 BOM 前置约束

实绩方向反过来,MES 把投入实绩和完成实绩写到接口文件,ERP 侧读进来计到指图上。数据分两类:投入实绩是构成品目的投入品目代码和数量;完成实绩是确认完成量、确认不良量、预计完成日。MES 侧按指图单位、按日汇总,如果 MES 内部对指图做了分割或合并,由 MES 侧先归并回一个指图再写文件,ERP 侧不做这个归并。这一点在联调时非常容易被忽略,MES 现场按工单拆分得很细,写到文件里就是一堆碎片,ERP 侧收到后不知道往哪张指图上计。

计上种别也有两种,运行时用变体选:一种是作业的累计实绩,一种是作业日别实绩。差别在于 ERP 侧收到的是「到目前为止一共做了多少」还是「今天做了多少」。选累计实绩,重复计上的风险低,但需要 MES 侧保证累计值单调;选日别实绩,ERP 侧需要自己按日期累加,一旦某天漏发就要补数。没有绝对对错,取决于 MES 侧能不能稳定给出累计口径。我见过一个项目中途从日别切换成累计,历史数据没有做基线,结果第一个月全部重复计上,返工花了两周。

约束里有三条是硬性的,踩了就直接报错进日志:

  • 倒冲品目的投入实绩不能从 MES 计上。倒冲的语义是 ERP 自己按 BOM 反算消耗,MES 再报一次投入就重复了。要改倒冲品目的投入数量,只能在 ERP 的作业确认里手工改。
  • 计上的构成品目必须是指图发行时就已经在 BOM 里的。制造现场临时用了 BOM 里没登记的料,MES 报上来会被拒。正确做法是先补 BOM 再重发指图,接口层兜不住。
  • 实绩不支持从 MES 侧修改或取消。已经计上的实绩要改,只能在 ERP 侧改。

这三条合起来,其实是在划一条线:MES 接口只负责新增一笔实绩,不负责修正一笔实绩。这个边界如果不在需求阶段说清楚,上线后一定会有现场要求「MES 里改一下同步过去」,那时候再改架构就贵了。

2.3 单工厂、1-2 次/天的前提为什么不能随便放宽

说明书把适用前提写得很窄:一个工厂内 ERP 和 MES 的连携;对象是发行制造指图的生产方式;抽取和计上都是批处理,一天 1-2 回;两侧 OS 限定在 Windows 和 Unix;接口文件通过文件共享访问,两侧必须能访问同一个文件;文件是文本,不改码转换,原样透传。

这些前提是这套机制的成立条件,并非出于保守。文件共享加管理文件锁这套排他方式,在单工厂、低频批处理下够用。一旦扩到多工厂、多 MES 实例共享一个目录,管理文件就成了单点,锁的粒度和命名规则都得重做。再往上,如果要求准实时,文件轮询的延迟根本满足不了,这时候才轮到消息中间件出场。所以读这份说明书要先接受它的定位:它是原型构建期的接口雏形,并非终态架构。很多翻车都出在把雏形直接当生产方案用,等发现问题时接口已经铺到十几个车间了。

3. 接口文件与排他控制:共享目录下怎么不打架

这套 MES 接口真正难的地方不在业务字段,而在两个独立系统共用一个目录时怎么保证不乱。文件是谁写、谁删、什么时候能删、删到一半崩了怎么办,说明书用一套很轻的机制回答了这些问题。理解这套机制,比背文件字段重要得多。

3.1 接口文件清单与文本格式、换行码变体

接口文件一共四类,按方向分两组:

文件方向内容生命周期
指图数据文件ERP 写 / MES 读指图头部信息MES 处理完后删除
构成数据文件ERP 写 / MES 读指图的构成品目MES 处理完后删除
投入实绩文件MES 写 / ERP 读投入品目代码、数量ERP 处理完后删除
完成实绩文件MES 写 / ERP 读完成量、不良量、预计完成日ERP 处理完后删除

格式上有三个开关都放在变体里:换行码、文件逻辑路径、日志保存期限。换行码在 Windows 格式和 Unix 格式之间选,逻辑路径不能写死,因为测试环境和生产环境的共享目录挂载点通常不一样。说明书写明文件原样透传、不做码制转换,这条要特别注意:如果一侧按固定宽度、一侧按分隔符解析,或者两边对全角半角的处理不一致,字段就会错位。真实项目里更稳妥的做法是约定成纯 ASCII 分隔文本,中文品目名单独放一个可选字段,别让编码问题进到主键里。

提示:换行码变体一旦在运行中修改,必须保证两侧同时切换,并从空目录开始。已经写了一半的文件用另一种换行码续写,读侧会出现整文件解析失败。

3.2 管理文件式排他控制:三个文件与处理规则

排他不是靠数据库锁,也不是靠文件锁 API,而是靠「管理文件存不存在」这个最朴素的状态。管理文件分两个:指图处理管理文件、实绩处理管理文件,分别保护两个方向。

处理规则只有三条:处理中创建管理文件;管理文件不存在时才执行处理;处理完成后删除管理文件。写成伪代码大概是这样:

" 管理文件排他(结构示意,非原程序) FORM check_lock USING p_kind TYPE string. " 管理文件存在 → 另一侧正在处理,本次直接跳过 IF file_exists( get_lock_path( p_kind ) ) = abap_true. MESSAGE 'other side is running' TYPE 'S'. LEAVE TO SCREEN 0. ENDIF. ENDFORM. FORM create_lock USING p_kind TYPE string. " 先创建,再干活;创建失败视为排他失败 OPEN DATASET get_lock_path( p_kind ) FOR OUTPUT IN TEXT MODE. CLOSE DATASET get_lock_path( p_kind ). ENDFORM. FORM delete_lock USING p_kind TYPE string. " 正常结束后才删;异常退出不删,由人工或超时策略清理 DELETE DATASET get_lock_path( p_kind ). ENDFORM.

p_kind用来区分方向,两个方向用两把锁,互不影响,这样抽取和计上可以并行跑,只有同一方向的并发会被挡。get_lock_path返回共享目录下的固定命名,别加时间戳,加时间戳等于没锁。

这套机制的好处是跨系统、跨 OS、不依赖任何数据库或中间件,ERP 和 MES 用各自的语言都能实现,只要对同一个目录做「创建文件、判断文件存在、删除文件」三个动作即可。坏处也明显:进程被强杀、机器断电、网络中断时,管理文件会残留,下一次批处理会一直跳过,日志里只写一句「另一侧处理中」,看起来像玄学。现场一般配一个巡检脚本,发现管理文件存在超过 N 分钟就告警,确认无进程后再人工删除。这是这套设计里唯一需要额外运维补丁的地方。

3.3 唯一键与重发判断:读侧去重的实现要点

同步规则有四条,每一条都会影响你怎么写读侧逻辑:

  1. 写侧永远追加,不修改已有记录。
  2. 删除只由读侧在确认处理完成后执行。
  3. 每个接口文件都有一个唯一键,读侧靠这个键判断数据是否已经处理过。
  4. 已经处理完的交易不支持通过接口变更,要改只能在各系统里手工处理。

第三条是重复发送的兜底。写侧可能因为上一轮状态没置上而重发同一条记录,也可能因为运维手动重跑而重复写文件,读侧必须能识别。实现上一般是在读侧维护一张已处理键表,读一条、查一次、没有才处理,处理成功后再把键写进去。这里有个细节:键表不能只放在内存里,因为读侧也会崩;也不能只放在接口文件里,因为文件处理完就删了。放数据库里、跟着计上动作放在同一个事务里,是更稳妥的做法。

第四条是很多人误判的地方:以为接口能做双向同步,其实只能单向新增。实绩一旦计上,MES 侧再改数量,ERP 侧不会接受,接口也不提供取消语义。现场如果确实要改,只能走 ERP 的手工确认。所以需求评审时一定要把这条写进验收标准,别等到 UAT 才发现流程走不通。

4. ZMAF001 与 ZMAF005:两个批处理程序的执行流程

两个程序对应两条链路,抽取是 ZMAF001,计上是 ZMAF005。说明书的程序规格章节写的是结构,不是逐行代码,这反而给了落地时的自由度:流程固定,实现语言和风格可以按项目习惯来。下面按执行顺序拆,每一步都标出容易出错的位置。

4.1 ZMAF001 制造指图抽取:从选择变体到 SEND 置位

入口先选变体,变体决定日期窗口、换行码、逻辑路径、抽取管理方式。选完变体之后的顺序是固定的:查锁、建锁、筛选、写文件、置状态、删锁。写成示意结构:

" ZMAF001 抽取主流程(结构示意,非原程序) REPORT zmaf001. SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001. PARAMETERS: p_vari TYPE vari-varient OBLIGATORY, " 变体名,决定换行码/路径/日期窗口/管理方式 p_days TYPE i DEFAULT 7. " 着手日窗口:今天往后 N 天 SELECTION-SCREEN END OF BLOCK b1. START-OF-SELECTION. PERFORM check_lock USING 'ORDER'. " 无指图处理管理文件才继续 PERFORM create_lock USING 'ORDER'. " 创建排他标记 PERFORM extract_orders. " 四个条件叠加筛选指图头 PERFORM extract_components. " 按已筛选指图取构成品目 PERFORM append_if_file. " 追加写两个接口文件,不覆盖 PERFORM set_send_status. " 全部成功后才置用户状态 SEND PERFORM delete_lock USING 'ORDER'. " 正常结束删锁

p_vari不是可有可无的装饰,它把环境差异全部外置了,同一份程序在测试和生产之间只换变体,不改代码。p_days控制窗口宽度,窗口太窄会漏掉远期指图,太宽会把还没排产的指图提前推给 MES,现场常见的取值是 3 到 7 天,具体看排产提前期。extract_orders内部要按四个条件依次过滤,注意状态判断要用系统状态和用户状态一起看,只看一个会漏。set_send_status必须在两个文件都写成功之后调用,任何一步失败就直接跳到删锁,不置状态,下一轮自动补抽。

这里有个性能上的现实问题:如果一次要抽几千张指图,逐张置用户状态会很慢,而且中途失败会留下半截状态。常见做法是分批提交,每 500 张一批,批内全成功才置状态,批间失败可重入。说明书没写这个细节,但现场数据量上来之后不加批处理基本跑不完时间窗。

4.2 ZMAF005 实绩计上:工作库兜底与二次计上防护

计上方向最怕的是重复计上。想象一张指图已经计了 100 件完成量,程序在写日志时崩溃,管理文件删了但接口文件没删,下一轮又读一遍,就变成 200 件。说明书的解法是先落工作库:

" ZMAF005 实绩计上主流程(结构示意,非原程序) START-OF-SELECTION. PERFORM check_lock USING 'CONF'. PERFORM create_lock USING 'CONF'. PERFORM read_if_file. " 读投入/完成实绩文件 PERFORM dedup_by_unique_key. " 按唯一键判断是否已处理 PERFORM stage_to_work_table. " 先落工作库,不直接计上 PERFORM post_components. " 投入实绩:构成品目 + 数量 PERFORM post_confirmation. " 完成实绩:完成量/不良量/预计完成日 PERFORM delete_if_file. " 计上成功后才删接口文件 PERFORM write_log. PERFORM delete_lock USING 'CONF'.

stage_to_work_table是关键的一步:把待计上的行先整批写进数据库工作区,提交之后再执行计上动作。这样即使计上中途异常,工作区里有完整记录,恢复时可以按工作区的状态判断哪些已经计过、哪些没有,避免整文件重跑带来的二次计上。dedup_by_unique_key和上一章的键表是同一套东西,两边共用一个去重表更省事。post_components里要显式检查倒冲品目和 BOM 存在性,命中就直接写错误日志并跳过该行,不能让一行错误拖垮整批。delete_if_file放在最后,且只在整批成功时执行,部分失败时保留文件、记录已处理键,下一轮从断点继续。

4.3 两级日志结构:开始结束文件与记录级日志

日志分两种,用途完全不同。开始结束文件只在处理开始和处理结束时各写一条,记录批次号、开始时间、结束时间、成功失败计数,用来快速判断「这一轮到底跑没跑、跑了多久」。记录级日志按行写,每一条接口记录一行,记录键值、处理结果、错误码,用来定位具体哪张指图、哪个品目出了问题。

日志保存期限放在变体里,默认一般 30 到 90 天。这里有个容易忽略的点:开始结束文件和记录级日志的保留期要分开配,前者短、后者长。开始结束文件只是运行监控,保留一周就够;记录级日志是排错依据,保留三个月更合适。如果只配一个期限,要么监控历史不够、要么磁盘被日志撑爆,这两个问题在不同的项目上都出现过。

5. 避坑与排查:五条现场血泪记录

这套机制本身不复杂,复杂的是异常路径。下面五条都是实际项目里反复出现的,每条按现象、原因、解决写,能对号入座的基本可以省掉一轮通宵。

5.1 接口文件没删导致第二天重复计上

现象:同一批完成实绩连续两天被计上,ERP 侧确认数量翻倍,日志显示两天都处理成功。

原因:计上程序在写日志之前崩溃,delete_if_file没执行到,接口文件留在目录里;第二天重跑时去重表因为事务回滚也没写进去,于是整文件重处理。

解决:把删除文件和写去重键放进同一个提交单元,先写键、再删文件,顺序不能反。再加一条巡检:接口文件存在超过 24 小时就告警,人工确认后再处理。

5.2 倒冲品目从 MES 报投入实绩被拒

现象:MES 侧投入实绩文件里某些品目每批都报错,错误日志写「品目不允许计上」,但其他品目正常。

原因:这些品目在 ERP 侧被设成倒冲,消耗由 ERP 按 BOM 反算,接口层不接受外部投入。

解决:在 MES 侧维护一份倒冲品目清单,写文件前过滤掉,或者把这些品目的投入数量改成在 ERP 作业确认里录。清单要跟着 BOM 变更同步,不能一次配完就不管。

5.3 换行码不一致导致整文件解析失败

现象:MES 侧读指图文件时第一行就报格式错误,用编辑器打开看内容完全正常。

原因:ERP 侧变体配的是 Unix 换行,MES 侧按 Windows 换行解析,整个文件被当成一行。

解决:换行码作为联调第一项验收内容,两侧同时切换、从空目录开始。上线后把这个配置纳入变更管控,改之前必须双方确认。

5.4 管理文件残留让批处理一直跳过

现象:连续几轮批处理日志只写「另一侧处理中」,实际另一侧并没有在跑,重启程序也没用。

原因:上一轮进程被强杀,管理文件没删掉,排他判断一直认为有人在处理。

解决:配超时巡检,管理文件存在超过设定时间就告警;确认无进程后手工删除。更彻底的做法是把进程 PID 写进管理文件内容,巡检时校验 PID 是否还活着,避免误判。

5.5 指图在 ERP 侧被改,MES 侧还按旧数据生产

现象:MES 已经按抽取到的指图开始生产,ERP 侧因为工程变更改了 BOM 或数量,两边对不上。

原因:说明书明确写了抽取后指图由 MES 侧管理,ERP 侧原则上不再改;但现实里工程变更绕不开,变更流程没和接口流程对齐。

解决:在变更流程里加一道检查,指图一旦置了 SEND 状态,ERP 侧修改要先通知 MES 侧冻结;或者约定变更只在下一张指图生效,不改已抽取的。这条靠技术堵不住,得靠流程。

6. 变体参数落地与上线前验证

参数落地的核心原则是:凡是环境相关的,全部进变体,代码里不留任何硬编码路径和日期。下面这张表是我按说明书整理的最小参数集,实施时逐项确认,缺一项都会在联调时暴露。

参数作用建议初始值
换行码决定文件按 Windows 还是 Unix 解析与 MES 侧一致,联调首项确认
文件逻辑路径指向共享目录挂载点测试/生产分开配,不写死
日志保存期限记录级日志保留天数90 天,开始结束文件单独配 7 天
着手日窗口抽取指图的日期范围3 到 7 天,按排产提前期调
抽取管理方式日志检查或 SEND 状态长期运行选 SEND
计上实绩种别累计实绩或日别实绩与 MES 汇总口径一致,中途不切换

上线前我会强制走一遍验证清单,顺序不能乱:先用空目录跑一次抽取,确认两个接口文件生成、行数和筛选条件对得上;再手工造一条重复记录重跑,确认读侧去重生效;然后模拟进程中断,确认管理文件残留能被巡检发现;最后跑一次完整往返,从抽取到计上到文件删除,检查两级日志是否齐全。这套流程走下来大概半天,但能挡掉后面大部分的返工。

说个我自己的教训。早年做一个类似的接口,嫌参数多,把换行码和路径写死在代码里,测试环境跑得好好的,上线当天 MES 侧整文件解析失败,排查了四个小时才发现是换行码。从那以后我每次接这类共享目录接口,第一件事就是把变体参数表拉出来逐项对,第二件事是让两侧各写一个最小解析脚本互相对跑一遍,确认没问题再谈业务字段。这套习惯救过我至少三次。希望帮到你。

本文还有配套的精品资源,点击获取