SAP ABAP顾问必看:销售订单转交货单的BAPI函数全解析

发布时间:2026/10/6 9:25:46
SAP ABAP顾问必看:销售订单转交货单的BAPI函数全解析 做SAP项目的朋友应该都有体会尤其是制造业或者外贸零售行业仓库每天几千行销售订单等着转交货单光靠VL01N一台台手工点手指都要点出腱鞘炎更别提同时还容易把装运点、交货日期填错。所以“根据订单自动/批量创建出库单”几乎是每个SD项目都绕不开的需求而这块的核心就落在几个关键的函数身上。这一篇是系列的第二篇。上一篇我们从业务角度梳理了销售订单到交货单的完整链路也把几个常用BAPI的作用和适用范围做了总览。这一篇更直接一点我把实际项目中真正用得最频、踩坑最多的几个“创建类”函数逐个拉出来讲包括参数怎么填、代码大概怎么组织、项目上遇到过的那些奇怪报错怎么排查。如果你是刚接手SD开发的ABAP顾问或者想搞清楚交货单搬砖逻辑的业务顾问这篇应该能帮你省掉不少翻SAP NOTE的时间。1. 先理清楚从销售订单到出库单系统到底走了一条什么路1.1 业务链条先回顾一下销售订单VA01确认后想要真正把货发给客户系统里必须存在一张“外向交货单”Outbound Delivery也就是咱们常说的出库单。这张单子形成后仓库才能按它拣货PGI前拣配、复核、装运然后做发货过账PGI过账库存成本。整个链路的触发点就是我们要讲的函数——根据销售订单的数据让系统自动生成一张交货单。SAP里这块走得是经典的“抬头 行项目 装运点 批次/序列号”多层结构所以函数也大多不是单一函数搞定而是“主导函数 配套增强 后续更新函数”的组合。很多刚学SD开发的朋友总问一个问题“既然VL01N能手工创建为什么还要写函数批量搞” 实际项目里80%的原因不是替代手工操作而是要做接口。比如CRM或者自建的电商订单系统推送订单到SAPSAP创建完销售订单后需要立刻自动创建交货单扔给WMS去发货这个动作必须程序化。另外一些周期性的批发订单一天上千条也不可能让人在SAP里慢慢点出来。所以函数列表就是我们在这种场景下的核心工具。1.2 本期函数清单总览既然标题叫“函数列表的介绍”我先把本篇会展开讲到的函数用一张表放在前面后面逐个用一个一个小节来拆。这样你读到后面对应章节时脑子里有个整体地图。函数名作用调用时机/适用场景BAPI_OUTB_DELIVERY_CREATE_SLS基于销售订单创建外向交货单最核心普通销售订单、退货单都能用BAPI_OUTB_DELIVERY_CREATE_STO基于STO单据创建外向交货单公司间/跨工厂调拨的STO场景WS_DELIVERY_UPDATE_2创建后再修改交货单行项目、数量、批次等交货单需要追加行、改量、拆批次时WS_DELIVERY_UPDATEWS_DELIVERY_UPDATE_2的旧版更新函数老项目维护新项目不建议再用BAPI_GOODSMVT_CREATE做发货过账PGI交货单确认后冲库存、生成会计凭证BAPI_SHIPMENT_CREATE创建装运单需要整车/物流计划跟交货单联动时需要提醒一句你大概率不会只调用其中一个函数就收工。比如你调BAPI_OUTB_DELIVERY_CREATE_SLS创建完发现数据不对回头又调WS_DELIVERY_UPDATE_2去改行项目最后过账又调BAPI_GOODSMVT_CREATE。所以这篇不仅是“单个函数怎么用”也在帮你建立一套“组合拳”的思维。2. BAPI_OUTB_DELIVERY_CREATE_SLS创建出库单的主武器2.1 核心参数逐个拆这个函数是SD顾问和ABAP顾问日常打交道最多的一个BAPI全称顾名思义就是“基于销售订单创建外向交货”。它的导入参数有几组很关键先说清楚它们分别管什么SALES_ORDER结构类型 BAPIDLVREF主要填销售订单号VBELN和行项目POSNR。注意如果你只填订单号不填行项目系统会尝试根据订单的完整交货计划去拆单有部分行项目不参与交货时这个字段就非常重要。DELIVERY_HEADER结构类型 BAPISHPDLVUPD用来填交货单抬头信息其中最常用的就是SHIP_POINT装运点、DELIV_DATE交货日期、DUE_DATE到期日、FACT_DATE拣配/实际发货日期。这些日期如果不传系统会按销售订单里的计划行默认值带出但你会经常发现默认值不是用户要的所以建议显式传值。DELIVERY_HEADER_X这个X结构是SAP BAPI风格的“更新开关”相当于告诉系统“哪些字段我要改”。很多新项目出问题就是只填了DELIVERY_HEADER、没填X结构结果字段更新不进去。EXTENSION_INBAPIPAREX 类型的内部表用来传一些自定义增强字段。SD交货单增强一般会用到这个参数比如挂一些客制化的文本、自定义字段。SYNCHRONOUS同步/异步开关。批量创建时我一般习惯置为“X”同步执行这样函数返回后立即能拿到交货单号方便后续处理省得还得轮询去查。导出参数里 DELIVERY_NUMBER 是新建成功的交货单号RETURN是BAPIRETURN结构里面放着成功消息、警告、报错信息。千万记得RETURN的类型在成熟ECC和S4版本里有差异某些版本返回的是BAPIRETURN2细节信息更多自己写代码前先SE37看参数列表别凭记忆硬写。2.2 一个能直接跑的代码示例下面这段是我在项目里会用的基础模板已经去掉具体的公司数据保留主干逻辑。逻辑上先通过SELECT把销售订单行项目查出来再循环去创建交货单。DATA: ls_sales_order TYPE bapidlvref, lt_sales_order TYPE TABLE OF bapidlvref, lt_sales_item TYPE TABLE OF bapidlvreftem, ls_delivery_header TYPE bapishpdlvupd, ls_delivery_header_x TYPE bapishpdlvupdx, ls_extension_in TYPE bapiparex, lt_extension_in TYPE TABLE OF bapiparex, lv_delivery_no TYPE bapishpdlvupd-deliv_numb, lt_return TYPE TABLE OF bapiret2, ls_return LIKE LINE OF lt_return. * 1. 准备销售订单行项目 SELECT vbeln, posnr INTO TABLE DATA(lt_vbap) FROM vbap WHERE vbeln p_vbeln. LOOP AT lt_vbap INTO DATA(ls_vbap). ls_sales_order-vbeln ls_vbap-vbeln. ls_sales_order-posnr ls_vbap-posnr. APPEND ls_sales_order TO lt_sales_order. ENDLOOP. * 2. 准备交货单抬头按项目需求传值 ls_delivery_header-deliv_date p_deliv_date. 交货日期 ls_delivery_header-ship_point p_ship_point. 装运点 ls_delivery_header-due_date sy-datum. ls_delivery_header_fact_date sy-datum. 拣配日期 ls_delivery_header_x-deliv_date abap_true. ls_delivery_header_x-ship_point abap_true. ls_delivery_header_x-due_date abap_true. ls_delivery_header_x_fact_date abap_true. * 3. 如果有增强字段往EXTENSION_IN里丢 * ls_extension_in-structure ZEDLVHEADER. * ... (对大字段做赋值) * APPEND ls_extension_in TO lt_extension_in. * 4. 调用BAPI CALL FUNCTION BAPI_OUTB_DELIVERY_CREATE_SLS EXPORTING sales_order lt_sales_order[] delivery_header ls_delivery_header delivery_header_x ls_delivery_header_x synchronously abap_true * extension_in lt_extension_in[] IMPORTING delivery_number lv_delivery_no return ls_return. * 5. 根据返回消息处理成功/失败 IF ls_return-type S OR ls_return-type E. IF ls_return-type E. ROLLBACK WORK. ELSE. IF lv_delivery_no IS NOT INITIAL. COMMIT WORK. ENDIF. ENDIF. ENDIF.代码看着不复杂但我必须提醒几个细节第一ls_delivery_header和ls_delivery_header_x里各字段的赋值顺序容易乱。很多项目在DEBUG时发现明明传了交货日期但进到VL01N界面时日期是空的十有八九是忘记传X结构。X结构的作用不是填字段值而是告诉BAPI“我要用外部值覆盖内部默认值”。这个理解到位以后调任何BAPI都不会犯迷糊。第二RETURN的结构。上面我用的是bapiret2因为新版本BAPI导出参数已经升级。如果你系统还是老内核ECC可能要用bapiret。建议在SE37里看一眼函数的“导出参数”页签以系统实际为准。第三COMMIT WORK的位置。如果在循环里调BAPI不要每个单都COMMIT一批处理完成后统一COMMIT提交性能能好很多事务也更好控制。2.3 最容易踩到的三个坑坑一销售订单虽然存在但系统提示“没有可交货的项目/交货已冻结”。原因多半是订单行项目未确认、交货冻结、甚至Credit被锁。这时候别急着怀疑BAPI先去VA03看一眼后台表VBAP里LFGSA交货冻结、LET01这些状态或者用VL01N手工创建一下看系统到底报什么。坑二缺装运点。即便SLS版函数能从销售订单带出装运点但订单的后台配置“装运条件 载重组 装运点确定”如果不完整BAPI也会直接报错。这属于配置问题开发把问题抛给SD顾问别自己在那儿瞎猜。坑三批量创建时突然崩溃程序一跑就是十几分钟最后拿到一堆篇报错。这种情况多半是没控制“SALES_ORDER行项目拆分的数量”和“批次拆分”。比如一张订单有100行你想创建成一张交货单结果系统因为“不同装运点”或“不同工厂”自动拆成3张。这个时候不只关注函数入参还要检查后台“交货拆分规则”。如果业务允许通常把“仅按工厂”拆分关掉让所有行都落在一张交货单上。3. BAPI_OUTB_DELIVERY_CREATE_STOSTO场景的特殊玩家3.1 STO与普通销售订单的本质区别先别急着往下看代码得先说清楚STO是什么。STOStock Transport Order库存转储订单在SAP里本质是一种特殊采购订单但又能像销售订单一样触发交货流程。常见于公司间调拨、工厂间调拨、或者“集团内销售”。如果你们项目有总部工厂往分公司仓库补货这种场景用的就是这玩意儿。既然本质是采购单就不能直接用BAPI_OUTB_DELIVERY_CREATE_SLS去创建交货否则系统压根找不到“销售订单”的对应关系。BAPI_OUTB_DELIVERY_CREATE_STO就是专门为这场景准备的它接收的是采购订单EBELN和行项目EBELP而不是VBELN/POSNR这是和SLS版函数最大的区别。3.2 关键参数与调用要点BAPI_OUTB_DELIVERY_CREATE_STO的导入参数也是“抬头 行 更新开关”这个套路但抬头和行项目的字段跟SLS版相比多了不少跟采购相关的控制。核心几组DELIVERY_HEADER同样用BAPISHPDLVUPDSHIP_POINT、DELIV_DATE这些照填。ITEMS / ITEMS_X结构类型BAPISDITM/BAPISDITMX这里既包含收货方信息也包含采购订单号EBELN、行项目EBELP。注意行项目里必须填REF_DOC参考单据号让系统知道你是基于哪张采购订单去建交货。REL_STO_CREATE部分版本里有这个参数标识是否允许“释放STO后立即创建”。如果这个开关没传对STO还在审批中你去创建交货单会被打回。代码骨架大致是这样DATA: lt_items TYPE TABLE OF bapisditm, ls_items TYPE bapisditm. ls_items-ref_doc p_ebeln. 采购订单号 ls_items-ref_item p_ebelp. 采购订单行 ls_items-ship_point p_ship_point. APPEND ls_items TO lt_items. CALL FUNCTION BAPI_OUTB_DELIVERY_CREATE_STO EXPORTING delivery_header ls_delivery_header delivery_header_x ls_delivery_header_x TABLES items lt_items * items_x lt_items_x return lt_return.我实际用下来的感受是STO版的函数比SLS版“娇贵”它对后台配置的依赖更重。比如交货类型、项目类别归属、库存地点找取逻辑任何一环断了都会在BAPI返回里报很底层的消息甚至只有E级别消息但不告诉你具体哪个配置缺失。所以遇到STO创建失败先别急着看函数代码先用VL10B或VL10C把该订单手工转一遍如果手工也转不出来那就是后台配置的问题跟函数本身没关系。3.3 什么时候用STO版什么时候用SLS版有些顾问会在这块犯迷糊比如项目里用户说“我有一张销售订单同时又是集团内调拨”就开始纠结该用哪个BAPI。我的建议就一条看“交货单单据类型怎么产生”一切以SO-Path为准。协议模式的集团内销售后台用的是“销售订单 → 交货单”流程选SLS真正的STO流程是“采购订单 → 交货单”选STO版。混淆使用最常见的报错是“没有指定订单项目”或“参考单据类型不允许”。这里放个对比表一目了然对比维度BAPI_OUTB_DELIVERY_CREATE_SLSBAPI_OUTB_DELIVERY_CREATE_STO前置单据销售订单VA01库存转储订单/采购订单ME21N参考字段VBELN/POSNREBELN/EBELP典型场景标准零售、批发、退货工厂调拨、公司间补货、跨工厂采购直发配置依赖相对低但要装运点高涉及STO流程配置常见报错交货冻结、装运点缺失找不到项目类别、释放状态不对选函数的本质不是“哪个名字看着像”而是明白你手里要处理的业务单据到底是什么类型。搞清楚这一个点SD里的交货单创建函数你基本就通了一半。4. 创建之后要改要过账WS_DELIVERY_UPDATE_2 与配套函数4.1 WS_DELIVERY_UPDATE_2能干什么很多项目里BAPI_OUTB_DELIVERY_CREATE_SLS创建出来的交货单行项目数量是“订单计划量”但到了真正拣货时仓库发现有两箱破损只能发95箱。这时候你不能重新删单再建成本太高通常做法是直接改交货单行项目数量。这就是WS_DELIVERY_UPDATE_2的出场时间。这个函数是VL02N的底层更新函数。它跟BAPI的区别在于它本身不做很复杂的业务校验更像一个“数据搬运工”你给它抬头数据LIKP、抬头更新开关LIKP_X以及行项目数据LIPS、行项目更新开关LIPS_X它就把这些字段按X结构的指示更新到交货单上。需要注意WS_DELIVERY_UPDATE_2这个名字听着像“老函数”但它并没有被废弃在S4里仍然能用。只是很多开发在调用时容易漏一个关键参数IF_LIPS_UPD——它是控制“是否更新行项目”的开关。如果不传经常出现抬头改了、行没改的诡异现象。所以调用前一定要在SE37里查一下这个函数当前的参数接口不同版本参数名会有差异。4.2 发货过账BAPI_GOODSMVT_CREATE 的配合使用交货单创建完、数量确认完下一步通常是发货过账PGI。手工做是VL02N里点“发货过账”程序化做法就是调BAPI_GOODSMVT_CREATE。它其实不是一个交货单专用函数而是一个通用货物移动函数但配合交货单时要往里传三样东西GOODSMVT_HEADER抬头信息PSTNG_DATE过账日期是必填DOC_DATE是凭证日期。GOODSMVT_ITEM行项目特别要注意字段 material物料、plant工厂、move_type移动类型。交货单PGI对应的移动类型通常是601销售出库。GOODSMVT_CODE移动代码。这里的GM_CODE要填“04”表示发货/外向交货。有人会问既然交货单上已经有数量、批次、库存地点了为什么BAPI_GOODSMVT_CREATE还得手工填一遍行项目因为货物移动函数本身不知道“哪张交货单”它只知道“有哪些物料要从哪个库位出多少”。所以在调用前你需要先通过循环交货单行项目把信息填进去再调用。这也是接口开发时最容易写反的地方有人觉得调了创建交货单的函数就等于过账了其实差着一个函数呢。这一部分我补充一个实用做法如果创建的出库单不需要单独修改直接创建后立即过账可以两段函数连调CALL FUNCTION BAPI_OUTB_DELIVERY_CREATE_SLS EXPORTING delivery_header ls_delivery_header delivery_header_x ls_delivery_header_x TABLES sales_order lt_sales_order return lt_return. IF lv_delivery_no IS NOT INITIAL. PERFORM frm_fill_goodsmvt USING lv_delivery_no CHANGING lt_goodsmvt_item. CALL FUNCTION BAPI_GOODSMVT_CREATE EXPORTING goodsmvt_header ls_goodsmvt_header goodsmvt_code ls_goodsmvt_code testrun abap_false TABLES goodsmvt_item lt_goodsmvt_item return lt_return. ENDIF.注意两个函数间不能COMMIT太早。有些项目里程序员习惯创建完立刻COMMIT这个习惯在单独创建交货单时没问题但如果后面跟着过账一定不要中间COMMIT否则两张单的凭证流可能就断开了排错特别麻烦。4.3 函数、更新函数与BDC录屏三者怎么选和很多SD顾问聊的时候发现一个讨论点既然有VL01N录屏BDC方案也能创建交货单那为什么还要用BAPI我的立场是能用BAPI优先用BAPI原因是BAPI返回结构清晰、错误处理可控、跳出SESSION事务后不会把屏幕上的错误混在一起在接口场景下更干净。但有一个例外当交货单创建过程中涉及大量客制化增强、自定义校验而这些增强又写在屏幕PBO/PAI里BAPI可能触发不到这时候BDC录屏反而更稳。而WS_DELIVERY_UPDATE这种“中间层”更新函数则更适合在BAPI基础之上做二次修改。单从维护角度讲BAPI 更新函数是目前SAP官方推荐路径也是我给别人做设计评审时最希望看到的方案。BDC可以作为Plan B但尽量不要让它成为首选毕竟录屏一旦碰上菜单调整脚本经常要重录维护成本真的高。5. 实操实录从订单到出库单的完整实现5.1 前提配置检查清单开始码代码之前我会先过一遍配置检查清单。项目上很多“莫名其妙”的问题最后都证明根本不是程序问题而是事前配置不完整。这块东西如果靠BAPI报错去反推往往要走很多弯路。第一检查装运点确定。SE11里看TVAK销售单据类型、TVTW装运点、TPOP装运点确定组合确保订单类型有对应的装运点否则BAPI创建时直接“未找到装运点”。第二检查交货类型。后台SPRO路径销售与分销 → 装运 → 交货 → 定义外向交货类型。确认销售订单类型对应的交货类型是否存在例如标准OR对应的交货类型LF。第三检查项目类别。从VBAP的PSTYV看是否有对应的项目类别并确认该项目类别的“交货相关”字段是打开的。退货单创建出库单时这一步尤其容易挂。第四检查自动批次确定。如果你物料启用了批次管理且交货时自动确定批次那么后台“批次确定”的搜索过程必须配好否则创建时系统找不到可用批次直接报错。第五检查客户主数据的装运条件。XD03客户主数据销售区域里“装运条件”字段如果为空交运点确定就相当被动也可能导致函数报错。这五条查完90%的“函数创建不了交货单”问题可以提前规避。别一上来就埋头Debug先让SD顾问把这些配置点给你过一遍开发效率能翻倍。5.2 完整示例批量读取订单并创建交货单实际项目里“批量”的需求最多。下面我给你一个相对完整的演示输入一个销售订单范围系统循环读取订单行批量创建交货单创建失败的行汇总输出日志。DATA: lt_vbeln_range TYPE RANGE OF vbeln, lv_vbeln TYPE vbeln, lv_delivery_no TYPE vbeln_vl, lt_sales_order TYPE TABLE OF bapidlvref, ls_sales_order TYPE bapidlvref. * 1. 查询待处理订单行 SELECT vbeln, posnr INTO TABLE DATA(lt_vbap) FROM vbap WHERE vbeln IN lt_vbeln_range AND lfgsa 无交货冻结 AND abgru . 无拒绝原因 * 2. 按订单合并行项目 SORT lt_vbap BY vbeln posnr. LOOP AT lt_vbap INTO DATA(ls_vbap). lv_vbeln ls_vbap-vbeln. AT NEW vbeln. CLEAR ls_sales_order. * 这里可根据需要初始化抬头参数 ENDAT. ls_sales_order-vbeln ls_vbap-vbeln. ls_sales_order-posnr ls_vbap-posnr. APPEND ls_sales_order TO lt_sales_order. AT END OF vbeln. * 3. 对每一张订单执行创建 PERFORM create_outbound_delivery USING ls_sales_order-vbeln CHANGING lv_delivery_no lt_return. ENDAT. ENDLOOP.这里面真正的创建逻辑封装在FORMcreate_outbound_delivery里里面就是第二节给的那段BAPI代码。封装的好处是日志、错误跟踪、重试图都要好做。再补充一个项目经验的点批量程序尽量带TESTRUN。把BAPI或其他函数里的TESTRUN参数利用好先跑一遍检查确认没有错误后再正式跑。这样能非常有效地避免批量跑一半、回头要删一大堆错误单的尴尬场面。5.3 结果验证与日志设计函数跑完了不等于活干完了。程序一定要把结果写进自建日志表而不是仅仅输出到ALV就算了。我一般会在自建表里存销售订单号、行项目、创建出的交货单号、状态、返回消息、时间戳、执行用户。原因很简单接口场景中下游WMS/OMS系统需要拿着交货单号做后续动作。如果SAP这边创建完成但日志没记录下游查询不到交货单两套系统直接架起一座断桥。而一旦出现数据不一致日志表就能帮你快速定位到底订单创建失败了还是创建成功但没告诉下游另外针对过账环节建议在日志里加一个“PGI状态字段”用来记录交货单是否已经发货过账。很多项目都会用状态字段做自动化重试比如WMS反馈说仓库没收到系统可以通过REST接口重新推送这张交货单的过账信息。6. 常见问题与排查技巧实录6.1 典型报错速查表报错/现象原因解决方案订单有交货冻结函数返回“no items due for delivery”VBAP-LFGSA字段被冻结清冻结VL01N里解除或直接更新VBAP再创建未找到装运点配置缺装运点确定SPRO配置装运点确定检查客户主数据装运条件BAPI返回E但报文是空无库存/批次查找失败查物料库存、批次配置自动批次确定搜索过程创建出的交货单数量不对行项目类别或拆分规则影响检查后台存储过程“定义交货项分类”“定义批量拆分规则”抬头日期没更新进去X结构没传检查DELIVERY_HEADER_X更新开关COMMIT后找不到交货单调用顺序错或COMMIT提前确保COMMIT在BAPI返回成功后再执行STO创建失败提示“单据类型不允许”用错了BAPI混用SLS和STO确认前置单据类型使用BAPI_OUTB_DELIVERY_CREATE_STO6.2 顾问级避坑经验我再加几条只有实际项目里摸爬滚打才能攒出来的经验。第一能用工作组Workgroup就尽量别单步循环。比如需要给3000张订单创建交货循环里调BAPI每次调用都要占一个数据库更新周期3000个循环跑下来很痛苦。你可以考虑分批提交每100张COMMIT一次日志也按批次记录出错时回滚范围更精准。第二注意单位换算。BAPI的DELIVERY_HEADER里如果涉及到重量、体积函数会根据物料主数据自动带出。但如果你从外部系统传入的是“箱数”那得先根据包装关系换算成基本单位或者销售单位否则交货单上的数量单位会跟库存单位不匹配PGI时直接报“数量超过库存”。第三批次确定性增强要谨慎。有时用户要求交货单自动带出“最早过期批次”但标准批次确定策略选不出来需要写一个增强。这种增强通常在交货单创建BAPI的ExtensionIn里传搜索条件。注意这种逻辑不要硬改成“优先选某个批次”最好做成可控的“备选策略”否则呆滞库存全部被优先出掉财务那边很快就来找你了。第四程序里凡是改过交货单后面想回到VL02N界面修改系统可能会提示“数据已被外部程序锁定”。这是因为你用WS_DELIVERY_UPDATE_2更新后没有调用DEQUEUE去释放对象锁。如果遇到这种提示用SM12看一下锁对象或者代码里在更新完成后调DEQUEUE_EVVL_LIKP释放。这个坑非常隐蔽很多人查到死都查不出来。第五版本兼容性。S4 HANA的BAPI接口比ECC阶段收敛了不少比如RETURN类型很多从BAPIRETURN升级到了BAPIRET2。不要在代码里写死“BAPIRETURN”否则传输到新环境直接激活失败。用前SE37核对是最稳的。尾声做SD模块的这几年我越来越觉得“函数列表”这类内容光看不练是不行的。你背得出BAPI_OUTB_DELIVERY_CREATE_SLS每个参数不如亲手在系统里调一次按我说的把X结构漏掉、装运点传空再有意识地去读一遍返回报文记忆会深得多。系列写到第二篇我尽量把每个函数在项目中真正用得上的细节都摊出来讲但每套系统的配置、增强和用户习惯都不同所以你落地时肯定还会遇到自己特有的问题。我自己实际做项目时有个习惯凡是SD交货单相关的新开发都会先把手动VL01N操作流程完整走一遍记录每一步涉及的TCODE、字段、报错再对照BAPI参数一个一个映射过去。这个方法帮我避掉过很多坑也方便我回头跟用户解释“这个函数为什么这么设计”。这套方法同样推荐给准备深入研究函数列表的读者。下一篇我计划讲讲“增强怎么落到创建交货单的BAPI里”比如批次确定增强、装运点覆盖、自定义字段传递这些都是接口项目躲不开的硬骨头到时我们再接着聊。