Java多层翻页网络爬虫实战(以搜房网为例)

目录

本文为原创博客,仅供技术学习使用。未经允许,禁止将其复制下来上传到百度文库等平台。如有转载请注明本文博客的地址(链接)

本人师兄所做的机器学习网站欢迎大家访问http://www.datalearner.com/blog

分析所要爬取的数据

在爬虫之前需要分析自己需要爬的数据。本文爬取的是所有http://esf.hf.fang.com/链接对应的房源的id,title,url。如下图所示:

这里写图片描述

这属于第一层所要获取的数据。第二层是获取每个房源对应的详细信息。其爬取的种子url,来自于第一层所获得的所有url。如下图所示:为第二层次所要获取的信息内容。
这里写图片描述

爬虫框架

本文的爬虫框架如下图所示:
有不明白框架里的内容含义的话,请看我写的其他相关博客。

基于java的网络爬虫框架(实现京东数据的爬取,并将插入数据库):
http://blog.csdn.net/qy20115549/article/details/52203722
Java多线程网络爬虫(时光网为例):http://blog.csdn.net/qy20115549/article/details/52648631

这里写图片描述

首先,我的工程都是使用maven建的,不会使用maven的,请看之前写的网络爬虫基础。使用spring MVC框架编写过网站的同学,可以看出框架的重要性与逻辑性。在我的网络爬虫框架中,包含的package有db、main、model、parse、util五个文件。

db:主要放的是数据库操作文件,包含MyDataSource【数据库驱动注册、连接数据库的用户名、密码】,MYSQLControl【连接数据库,插入操作、更新操作、建表操作等】。

model:用来封装对象,比如我要获取京东书籍的ID、书名、价格,则需要在model写入对应的属性。说的直白一些,封装的就是我要操作数据对应的属性名。有不明白的看之前写的一个简单的网络爬虫。

util:主要放的是httpclient的内容,主要作用时将main方法,传过来的url,通过httpclient相关方法,获取需要解析的html文件或者json文件等。

parse:这里面存放的是针对util获取的文件,进行解析,一般采用Jsoup解析;若是针对json数据,可采用正则表达式或者fastjson工具进行解析,建议使用fastjson,因其操作简单,快捷。

main:程序起点,也是重点,获取数据,执行数据库语句,存放数据。

model

用来封装对象,即我要爬取的相关信息。如针对搜房网而言,我需要爬取的数据为:发布房源的标题(title),这条房源信息的id等。

package model;
/*
 * author:合肥工业大学 管院学院 钱洋 
 *1563178220@qq.com
 *博客地址:http://blog.csdn.net/qy20115549/
*/
public class Address {
    private String addr_id;
    private String addr_url;
    private String title;
    private String craw_time;

    public String getAddr_id() {
        return addr_id;
    }
    public void setAddr_id(String addr_id) {
        this.addr_id = addr_id;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getAddr_url() {
        return addr_url;
    }
    public void setAddr_url(String addr_url) {
        this.addr_url = addr_url;
    }
    public String getCraw_time() {
        return craw_time;
    }
    public void setCraw_time(String craw_time) {
        this.craw_time = craw_time;
    }

}

以下Contents 表示的下面图片中的信息。
这里写图片描述

package model;
/*
 * author:合肥工业大学 管院学院 钱洋 
 *1563178220@qq.com
 *博客地址:http://blog.csdn.net/qy20115549/
*/
public class Contents {
    private String id;
    private String title;
    private String  publishtime;
    private String price;
    private String housetype;
    private String acreage;
    private String useacreage;
    private String years;
    private String orientation;
    private String floor;
    private String structure;
    private String decoration;
    private String type;
    private String buildingtype;
    private String propertyright;
    private String estate;
    private String school;
    private String facilities;

    public String getUseacreage() {
        return useacreage;
    }
    public void setUseacreage(String useacreage) {
        this.useacreage = useacreage;
    }
    public String getId() {
        return id;
    }
    public String getPublishtime() {
        return publishtime;
    }
    public void setPublishtime(String publishtime) {
        this.publishtime = publishtime;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getPrice() {
        return price;
    }
    public void setPrice(String price) {
        this.price = price;
    }
    public String getHousetype() {
        return housetype;
    }
    public void setHousetype(String housetype) {
        this.housetype = housetype;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getAcreage() {
        return acreage;
    }
    public void setAcreage(String acreage) {
        this.acreage = acreage;
    }
    public String getYears() {
        return years;
    }
    public void setYears(String years) {
        this.years = years;
    }
    public String getOrientation() {
        return orientation;
    }
    public void setOrientation(String orientation) {
        this.orientation = orientation;
    }
    public String getFloor() {
        return floor;
    }
    public void setFloor(String floor) {
        this.floor = floor;
    }
    public String getStructure() {
        return structure;
    }
    public void setStructure(String structure) {
        this.structure = structure;
    }
    public String getDecoration() {
        return decoration;
    }
    public void setDecoration(String decoration) {
        this.decoration = decoration;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getBuildingtype() {
        return buildingtype;
    }
    public void setBuildingtype(String buildingtype) {
        this.buildingtype = buildingtype;
    }
    public String getPropertyright() {
        return propertyright;
    }
    public void setPropertyright(String propertyright) {
        this.propertyright = propertyright;
    }
    public String getEstate() {
        return estate;
    }
    public void setEstate(String estate) {
        this.estate = estate;
    }
    public String getSchool() {
        return school;
    }
    public void setSchool(String school) {
        this.school = school;
    }
    public String getFacilities() {
        return facilities;
    }
    public void setFacilities(String facilities) {
        this.facilities = facilities;
    }

}

main

主方法,尽量要求简单,这里由于注释清晰,我就不多写了。

package main;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import model.Address;
import org.apache.http.ParseException;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import db.MYSQLControl;
import util.SouFangAddressFecter;
/*
 * author:合肥工业大学 管院学院 钱洋 
 *1563178220@qq.com
 *博客地址:http://blog.csdn.net/qy20115549/
*/
public class SouFangAddress {
    public static void main(String[] args) throws ParseException, IOException, SQLException, InterruptedException {
        HttpClient client = new DefaultHttpClient();                //初始化HTTPclient
        //初始地址
        String _url ="http://esf.hf.fang.com/";
        List<Address> addresses=new ArrayList<Address>();
        /调用函数,爬取数据
        addresses= SouFangAddressFecter.htmlGet(client, _url);
        //操作数据库,将获取的数据插入数据库
        MYSQLControl.executeAddressUpdate(addresses);

    }
}

util

SouFangAddressFecter类与HTTPUtils的作用时将main方法传来的url,使用httpclient的方法,向后台请求数据,并返回html。

package util;

import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.message.BasicHttpResponse;
/*
 * author:合肥工业大学 管院学院 钱洋 
 *1563178220@qq.com
 *博客地址:http://blog.csdn.net/qy20115549/
*/
public abstract class HTTPUtils {
    public static HttpResponse getRawHtml(HttpClient client, String personalUrl) {
        //创建请求方法,这里可采用get方式
        HttpGet getMethod = new HttpGet(personalUrl);
        HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
                HttpStatus.SC_OK, "OK");
        try {
            //执行get方法,请求数据
            response = client.execute(getMethod);

        } catch (IOException e) {

            e.printStackTrace();

        } finally {
            // getMethod.abort();
        }
        return response;
    }
}

SouFangAddressFecter 类中,一般获取entity (html)的内容一般一行代码就行了。

String entity = EntityUtils.toString (response.getEntity(),"UTF-8");

但通过我的分析,直接这样请求数据会出现乱码。原因是 Content-Encoding :gzip。数据是经过压缩的。所以,要先解压流数据。

 GzipDecompressingEntity zipRes = new GzipDecompressingEntity(response.getEntity());
             String s = EntityUtils.toString(zipRes, "gb2312");

完整的SouFangAddressFecter 的代码如下。

package util;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import model.Address;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.GzipDecompressingEntity;
import org.apache.http.util.EntityUtils;
import parse.SouFangAddressParser;

/*
 * author:合肥工业大学 管院学院 钱洋 
 *1563178220@qq.com
 *博客地址:http://blog.csdn.net/qy20115549/
*/
public class SouFangAddressFecter {
    public static List<Address> htmlGet (HttpClient client, String url) throws ParseException, IOException, SQLException, InterruptedException {
        List<Address> AddressInfo = new ArrayList<Address>();
        HttpResponse response = HTTPUtils.getRawHtml(client, url);      
        int StatusCode = response.getStatusLine().getStatusCode();
        if(StatusCode == 200){
             //由于此方法总是出现乱码
//          String entity = EntityUtils.toString (response.getEntity(),"UTF-8");
            //输出实体内容,不会乱码,乱码解决。由于数据是通过zip压缩的
             GzipDecompressingEntity zipRes = new GzipDecompressingEntity(response.getEntity());
             String s = EntityUtils.toString(zipRes, "gb2312");
            //解析实体内容
            AddressInfo = SouFangAddressParser.getdata(s);
            EntityUtils.consume(response.getEntity());
        }else {
            //关闭HttpEntity的流实体
            EntityUtils.consume(response.getEntity());
        }

        return AddressInfo;

    }
}

parse

此部分内容复制解析SouFangAddressFecter传过来的内容,即html。这里面包含了如何翻页。

package parse;

import java.io.IOException;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import model.Address;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
/*
 * author:合肥工业大学 管院学院 钱洋 
 *1563178220@qq.com
 *博客地址:http://blog.csdn.net/qy20115549/
 */
public class SouFangAddressParser {

    public static List<Address> getdata(String entity) throws SQLException, InterruptedException, IOException {
        List<Address> addresses = new ArrayList<Address>();
        //获取html文件
        Document doc = Jsoup.parse(entity);
        //获取总页数
        int sumpages=Integer.parseInt(doc.select("div[class=fanye gray6]").select("span[class=txt]").text().replaceAll("\\D", ""));
        //由于此网站,第一页和第二页等有重复的房源,有重读的id。防止有重复id出现,这里使用map
        Map<String, Integer> keymap=new HashMap<String, Integer>();
        for (int i = 1; i < sumpages; i++) {
            String everypageurl="http://esf.hf.fang.com/house/i3"+i;
            //这里我就直接用Jsoup请求了
            Document document = Jsoup.connect(everypageurl).timeout(50000).userAgent("bbbb").get();
            Elements elements=document.select("dl[id~=D03_?]");
            //获取每一个子内容
            for (Element ele:elements) {
                String id=ele.select("dd[class=info rel floatr]").select("p").select("a").attr("href").replaceAll("/chushou/", "").replaceAll(".htm", "");
                if (!keymap.containsKey(id)){
                    keymap.put(id, 1);
                    String url="http://esf.hf.fang.com/"+ele.select("dd[class=info rel floatr]").select("p").select("a").attr("href");
                    String title=ele.select("dd[class=info rel floatr]").select("p[class=title]").select("a").text();
                    Date date=new Date();
                    DateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String craw_time=format.format(date);
                    Address address = new Address();
                    address.setAddr_id(id);
                    address.setAddr_url(url);
                    address.setCraw_time(craw_time);
                    address.setTitle(title);
                    addresses.add(address);
                }
            }
        }
        //获取拼接地址

        return addresses;
    }
}

db数据库操作

db中包含两个java文件,MyDataSource,MYSQLControl。这两个文件的作用已在前面说明了。

package db;

import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
/*
 * author:合肥工业大学 管院学院 钱洋 
 *1563178220@qq.com
 *博客地址:http://blog.csdn.net/qy20115549/
*/
public class MyDataSource {

    public static DataSource getDataSource(String connectURI){
        BasicDataSource ds = new BasicDataSource();
         //MySQL的jdbc驱动
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUsername("root");              //所要连接的数据库名
        ds.setPassword("112233");                //MySQL的登陆密码
        ds.setUrl(connectURI);
        return ds;

    }

}
package db;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import model.Address;
import model.Contents;

/*
 * author:合肥工业大学 管院学院 钱洋 
 *1563178220@qq.com
 *博客地址:http://blog.csdn.net/qy20115549/
*/
public class MYSQLControl {
    static final Log logger = LogFactory.getLog(MYSQLControl.class);
    static DataSource ds = MyDataSource.getDataSource("jdbc:mysql://127.0.0.1:3306/soufang");
    static QueryRunner qr = new QueryRunner(ds);
    //查询数据的类
    public static <T> List<T> getListInfoBySQL (String sql, Class<T> type ){
        List<T> list = null;
        try {
            list = qr.query(sql,new BeanListHandler<T>(type));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list;
    }
    //插入数据soufang_address
    public static void executeAddressUpdate(List<Address> addresses) throws SQLException {
        //定义一个Object数组,行列
        Object[][] params = new Object[addresses.size()][4];
        for ( int i=0; i<params.length; i++ ){
            params[i][0] = addresses.get(i).getAddr_id();
            params[i][1] = addresses.get(i).getTitle();
            params[i][2] = addresses.get(i).getAddr_url();
            params[i][3] = addresses.get(i).getCraw_time();
        }
        try{
            qr.batch("insert into soufang_address (id, title,url,craw_time)"
                    + "values (?,?,?,?)", params);
        }catch( Exception e){
            logger.error(e);
        }

    }

    //操作数据库,插入房源的详细信息
    public static void executeContentInsert(List<Contents> contentinfo) throws SQLException {
        Object[][] params = new Object[contentinfo.size()][18];
        for ( int i=0; i<params.length; i++ ){
            params[i][0] = contentinfo.get(i).getId();
            params[i][1] = contentinfo.get(i).getTitle();
            params[i][2] = contentinfo.get(i).getPublishtime() ;
            params[i][3] = contentinfo.get(i).getPrice();
            params[i][4] = contentinfo.get(i).getHousetype();
            params[i][5] = contentinfo.get(i).getAcreage() ;
            params[i][6] = contentinfo.get(i).getUseacreage();
            params[i][7] = contentinfo.get(i).getYears();
            params[i][8] = contentinfo.get(i).getOrientation() ;
            params[i][9] = contentinfo.get(i).getFloor();
            params[i][10] = contentinfo.get(i).getStructure();
            params[i][11] = contentinfo.get(i).getDecoration() ;
            params[i][12] = contentinfo.get(i).getType();
            params[i][13] = contentinfo.get(i).getBuildingtype();
            params[i][14] = contentinfo.get(i).getPropertyright() ;
            params[i][15] = contentinfo.get(i).getEstate() ;
            params[i][16] = contentinfo.get(i).getSchool();
            params[i][17] = contentinfo.get(i).getFacilities() ;
        }
        try{
            qr.batch("insert into soufang_content (id, title,publishtime, price,housetype,acreage,useacreage,years,orientation,floor,structure,decoration,type,buildingtype,propertyright,estate,school,facilities)"
                    + "values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", params);
            System.out.println("共插入:\t"+contentinfo.size()+"条数据!");
        }catch( Exception e){
            logger.error(e);
        }

    }
}

爬虫如何实现翻页(地址拼接)

如下图所示,为搜房网的页码,对应的html标签信息。
这里写图片描述

使用Jsoup将总页数获取下来,然后采用循环,爬虫每页内容。这里涉及到url的拼接。我们发现第二页和第三页的地址分别是如下两个图。
这里写图片描述
这里写图片描述

以下是代码表示:

//获取总页数
int sumpages=Integer.parseInt(doc.select("div[class=fanye gray6]").select("span[class=txt]").text().replaceAll("\\D", ""));
for (int i = 1; i < sumpages; i++){
    //地址拼接
    String everypageurl="http://esf.hf.fang.com/house/i3"+i;
    //采用Jsoup获取每一个的响应数据,并解析
    ocument document = Jsoup.connect(everypageurl).timeout(50000).userAgent("bbbb").get();
    //解析数据。。。。。。。
}

网络爬虫如何解决主键重复问题

在写网络爬虫时,我们经常会遇到置顶帖。这种置顶帖在每页都有。一种解决的办法,我直接利用split的方法,将前半部分过滤。另一种办法是使用map的方法。
由于搜房网,在每一页都有相同的信息,其id也是一样。为此,我使用map的方法,过滤掉重复数据,相同数据只保留一条。

//创建map用来过滤数据
Map<String, Integer> keymap=new HashMap<String, Integer>();
        for (int i = 1; i < sumpages; i++) {
            String everypageurl="http://esf.hf.fang.com/house/i3"+i;
            //这里我就直接用Jsoup请求了
            Document document = Jsoup.connect(everypageurl).timeout(50000).userAgent("bbbb").get();
            Elements elements=document.select("dl[id~=D03_?]");
            //获取每一个子内容
            for (Element ele:elements) {
                String id=ele.select("dd[class=info rel floatr]").select("p").select("a").attr("href").replaceAll("/chushou/", "").replaceAll(".htm", "");
                //如果不包含id,则获取数据,否则还未为原来的数据
                if (!keymap.containsKey(id)){
                    keymap.put(id, 1);
                    String url="http://esf.hf.fang.com/"+ele.select("dd[class=info rel floatr]").select("p").select("a").attr("href");
                    String title=ele.select("dd[class=info rel floatr]").select("p[class=title]").select("a").text();
                }
            }
        }

本文为原创博客,仅供技术学习使用。未经允许,禁止将其复制下来上传到百度文库等平台。

根据BAPI_ALM_ORDER_MAINTAIN源代码分析原因: FUNCTION bapi_alm_order_maintain. *"---------------------------------------------------------------------- *"*"Local Interface: *" IMPORTING *" VALUE(IV_MMSRV_EXTERNAL_MAINTENACE) TYPE BAPI_FLAG OPTIONAL *" TABLES *" IT_METHODS STRUCTURE BAPI_ALM_ORDER_METHOD *" IT_HEADER STRUCTURE BAPI_ALM_ORDER_HEADERS_I OPTIONAL *" IT_HEADER_UP STRUCTURE BAPI_ALM_ORDER_HEADERS_UP OPTIONAL *" IT_HEADER_SRV STRUCTURE BAPI_ALM_ORDER_SRVDAT_E OPTIONAL *" IT_HEADER_SRV_UP STRUCTURE BAPI_ALM_ORDER_SRVDAT_UP OPTIONAL *" IT_USERSTATUS STRUCTURE BAPI_ALM_ORDER_USRSTAT OPTIONAL *" IT_PARTNER STRUCTURE BAPI_ALM_ORDER_PARTN_MUL OPTIONAL *" IT_PARTNER_UP STRUCTURE BAPI_ALM_ORDER_PARTN_MUL_UP OPTIONAL *" IT_OPERATION STRUCTURE BAPI_ALM_ORDER_OPERATION OPTIONAL *" IT_OPERATION_UP STRUCTURE BAPI_ALM_ORDER_OPERATION_UP OPTIONAL *" IT_RELATION STRUCTURE BAPI_ALM_ORDER_RELATION OPTIONAL *" IT_RELATION_UP STRUCTURE BAPI_ALM_ORDER_RELATION_UP OPTIONAL *" IT_COMPONENT STRUCTURE BAPI_ALM_ORDER_COMPONENT OPTIONAL *" IT_COMPONENT_UP STRUCTURE BAPI_ALM_ORDER_COMPONENT_UP OPTIONAL *" IT_OBJECTLIST STRUCTURE BAPI_ALM_ORDER_OBJECTLIST OPTIONAL *" IT_OBJECTLIST_UP STRUCTURE BAPI_ALM_ORDER_OLIST_UP OPTIONAL *" IT_OLIST_RELATION STRUCTURE BAPI_ALM_OLIST_RELATION OPTIONAL *" IT_TEXT STRUCTURE BAPI_ALM_TEXT OPTIONAL *" IT_TEXT_LINES STRUCTURE BAPI_ALM_TEXT_LINES OPTIONAL *" IT_SRULE STRUCTURE BAPI_ALM_ORDER_SRULE OPTIONAL *" IT_SRULE_UP STRUCTURE BAPI_ALM_ORDER_SRULE_UP OPTIONAL *" IT_TASKLISTS STRUCTURE BAPI_ALM_ORDER_TASKLISTS_I OPTIONAL *" EXTENSION_IN STRUCTURE BAPIPAREX OPTIONAL *" RETURN STRUCTURE BAPIRET2 OPTIONAL *" ET_NUMBERS STRUCTURE BAPI_ALM_NUMBERS OPTIONAL *" IT_REFORDER_ITEM STRUCTURE BAPI_REFORDER_ITEM_I OPTIONAL *" IT_REFORDER_ITEM_UP STRUCTURE BAPI_REFORDER_ITEM_UP OPTIONAL *" IT_REFORDER_SERNO_OLIST_INS STRUCTURE *" BAPI_REFORDER_SERNO_OLIST_I OPTIONAL *" IT_REFORDER_SERNO_OLIST_DEL STRUCTURE *" BAPI_REFORDER_SERNO_OLIST_I OPTIONAL *" IT_PRT STRUCTURE BAPI_ALM_ORDER_PRT_I OPTIONAL *" IT_PRT_UP STRUCTURE BAPI_ALM_ORDER_PRT_UP OPTIONAL *" IT_REFORDER_OPERATION STRUCTURE BAPI_REFORDER_OPERATION *" OPTIONAL *" IT_SERVICEOUTLINE STRUCTURE BAPI_ALM_SRV_OUTLINE OPTIONAL *" IT_SERVICEOUTLINE_UP STRUCTURE BAPI_ALM_SRV_OUTLINE_UP *" OPTIONAL *" IT_SERVICELINES STRUCTURE BAPI_ALM_SRV_SERVICE_LINE OPTIONAL *" IT_SERVICELINES_UP STRUCTURE BAPI_ALM_SRV_SERVICE_LINE_UP *" OPTIONAL *" IT_SERVICELIMIT STRUCTURE BAPI_ALM_SRV_LIMIT_DATA OPTIONAL *" IT_SERVICELIMIT_UP STRUCTURE BAPI_ALM_SRV_LIMIT_DATA_UP *" OPTIONAL *" IT_SERVICECONTRACTLIMITS STRUCTURE *" BAPI_ALM_SRV_CONTRACT_LIMITS OPTIONAL *" IT_SERVICECONTRACTLIMITS_UP STRUCTURE *" BAPI_ALM_SRV_CONTRACT_LIMITS_U OPTIONAL *" ET_NOTIFICATION_NUMBERS STRUCTURE BAPI_ALM_NOTIF_NUMBERS *" OPTIONAL *" IT_PERMIT STRUCTURE BAPI_ALM_ORDER_PERMIT OPTIONAL *" IT_PERMIT_UP STRUCTURE BAPI_ALM_ORDER_PERMIT_UP OPTIONAL *" IT_PERMIT_ISSUE STRUCTURE BAPI_ALM_ORDER_PERMITISSUE OPTIONAL *" IT_ESTIMATED_COSTS STRUCTURE BAPI_ALM_ORDER_COSTS_EST_I *" OPTIONAL *" IT_HEADER_JVA STRUCTURE BAPI_ALM_ORDER_JVA OPTIONAL *" IT_HEADER_JVA_UP STRUCTURE BAPI_ALM_ORDER_JVA_UP OPTIONAL *" IT_ADDITIONAL_TEXT STRUCTURE BAPI_ALM_CC4_ADDITIONAL_TEXT *" OPTIONAL *"---------------------------------------------------------------------- ENHANCEMENT-POINT bapi_alm_order_maintain_g8 SPOTS es_saplibapi_alm_order STATIC. ENHANCEMENT-POINT bapi_alm_order_maintain_g6 SPOTS es_saplibapi_alm_order. * BAPI Funktionsbaustein zum Bearbeiten von ALM Aufträgen (PM/CS) * Die gewünschten Funktionen müssen über eine Methodentabelle * übergeben werden. Darin stehen die auszuführenden Methoden. * Die dazugehörigen Daten sind in den einzelnen Datentabellen * zuzuordnen. * Weitere Informationen befinden sich im BAPI Explorer unter * Instandhaltungsabwicklung bzw. Serviceabwicklung * Datendefinitionen *************************************** DATA lt_methods TYPE bapi_alm_order_method_t. * Zu bearbeitende Aufträge, die gelesen werden müssen DATA lt_orders TYPE almb_ord_pre_tab. * Methodenreihenfolge DATA lt_method_level TYPE almb_proc_level_tab. * Interne Datentabellen *********************************** * Auftragsköpfe DATA lt_caufvd TYPE almb_caufvd_tab_int. DATA lt_caufvd_up TYPE almb_caufvd_up_tab_int. * Servicedaten Auftragsköpfe DATA lt_pmsdo TYPE almb_caufvd_srv_tab_int. DATA lt_pmsdo_up TYPE almb_caufvd_srv_up_tab_int. * Auftragsköpfe (extern) DATA lt_bapihead TYPE almb_caufvd_tab. DATA ls_bapihead TYPE LINE OF almb_caufvd_tab. DATA lt_bapihead_up TYPE almb_caufvd_up_tab. DATA ls_bapihead_up TYPE LINE OF almb_caufvd_up_tab. DATA lt_bapihead_old TYPE almb_caufvd_tab. DATA lt_bapihead_old_up TYPE almb_caufvd_up_tab. * Servicedaten Auftragsköpfe (extern) DATA lt_bapisrvcdata TYPE almb_caufvd_srv_tab. DATA ls_bapisrvcdata TYPE LINE OF almb_caufvd_srv_tab. DATA lt_bapisrvcdata_up TYPE almb_caufvd_srv_up_tab. DATA ls_bapisrvcdata_up TYPE LINE OF almb_caufvd_srv_up_tab. DATA lt_bapisrvcdata_old TYPE almb_caufvd_srv_tab. DATA lt_bapisrvcdata_old_up TYPE almb_caufvd_srv_up_tab. * Auftragskopfdaten nach BADI für Abwärtskompatibilität DATA ls_header TYPE bapi_alm_order_headers_i. DATA ls_header_up TYPE bapi_alm_order_headers_up. DATA ls_header_srv TYPE bapi_alm_order_srvdat_e. DATA ls_header_srv_up TYPE bapi_alm_order_srvdat_up. DATA lt_header TYPE TABLE OF bapi_alm_order_headers_i. DATA lt_header_up TYPE TABLE OF bapi_alm_order_headers_up. DATA lt_header_srv TYPE TABLE OF bapi_alm_order_srvdat_e. DATA lt_header_srv_up TYPE TABLE OF bapi_alm_order_srvdat_up. * Userstatus DATA lt_userstatus TYPE almb_userstatus. * Partner DATA lt_partner TYPE almb_partner_tab. DATA lt_partner_up TYPE almb_partner_up_tab. * Vorgänge DATA lt_afvgd TYPE almb_afvgd_tab. DATA lt_afvgd_up TYPE almb_afvgd_up_tab. * Anordnungsbeziehungen DATA lt_afabd TYPE almb_afabd_tab. DATA lt_afabd_up TYPE almb_afabd_up_tab. * Komponenten DATA lt_resbd TYPE almb_resbd_tab. DATA lt_resbd_up TYPE almb_resbd_up_tab. * Objektliste DATA lt_riwol TYPE almb_riwol_tab. DATA lt_riwol_up TYPE almb_riwol_up_tab. * Objectlist: Relation Operation to Objectlist DATA lt_olist_relation TYPE almb_olist_relation_tab. * Task lists DATA lt_tasklists TYPE ibapi_order_tasklists_i_t. * Settlement rules DATA lt_cobl TYPE almb_cobl_tab. DATA lt_cobl_up TYPE almb_cobl_up_tab. * Langtexte DATA lt_text TYPE almb_text_tab. DATA lt_text_add TYPE almb_cc4_add_text_tab. "note 2756658 DATA lt_text_lines TYPE tlinetab. * Rückgabe der Nachrichten DATA lt_messages TYPE bal_t_msg. DATA ls_messages TYPE bal_s_msg. DATA ls_return LIKE LINE OF return[]. DATA lv_error TYPE sy-subrc. *Refurbishment order DATA lt_afpod TYPE ibapi_afpod_tt. DATA lt_afpod_resbd TYPE ibapi_reforder_comp_tt. DATA lt_serno_olist_ins TYPE reford_serno_olist_t. DATA lt_serno_olist_del TYPE reford_serno_olist_t. DATA lt_afpod_up TYPE ibapi_afpod_update_tt. DATA lt_afpod_resbd_up TYPE ibapi_reforder_comp_update_tt. DATA lt_reford_afvgd TYPE almb_afvgd_tab. *PRTs DATA lt_prt TYPE bapi_alm_order_prt_i_t. DATA lt_prt_up TYPE bapi_alm_order_prt_up_t. *Service packages DATA lt_serviceoutline TYPE bapi_alm_srv_outline_t. DATA lt_serviceoutline_up TYPE bapi_alm_srv_outline_up_t. DATA lt_servicelines TYPE bapi_alm_srv_service_line_t. DATA lt_servicelines_up TYPE bapi_alm_srv_service_line_up_t. DATA lt_servicelimit TYPE bapi_alm_srv_limit_data_t. DATA lt_servicelimit_up TYPE bapi_alm_srv_limit_data_up_t. DATA lt_servicecontractlimits TYPE bapi_alm_srv_contract_limit_t. DATA lt_servicecontractlimits_up TYPE bapi_alm_srv_contr_limits_u_t. * Note 1989741 - begin DATA: ls_extension_up TYPE almb_extension_up. DATA: lt_extension_up TYPE almb_extension_up_tab. * Note 1989741 - end *Permits DATA lt_permit TYPE eam_t_permit_order. DATA lt_permit_up TYPE eam_t_permit_order_up. DATA lt_permit_issue TYPE eam_t_permit_issue. * Estimated costs DATA: lt_est_cost TYPE bapi_alm_order_costs_est_i_tt. " 1672966 EAMCC PM110 * Settlement profiles DATA: lt_settlmt_profile TYPE almb_settlmt_profile_tab. * >>>>> Begin note 2304265: DFPS specific variables data lv_method_del type abap_bool. * <<<<< End note 2304265 * DATA lt_serno_olist_up TYPE REFORD_SERNO_OLIST_UPDATE_TT. FIELD-SYMBOLS <fs_olist_relation> LIKE LINE OF lt_olist_relation. FIELD-SYMBOLS <fs_methods> LIKE LINE OF lt_methods. "1837200 cl_eam_usage=>insert('BAPI_ALM_ORDER_MAINTAIN'). * BADIs * Vorwärtsdeklaration für exit handler BAdI CLASS cl_exithandler DEFINITION LOAD. * Interfacereferenz für BAdI STATICS sr_modify_input_data TYPE REF TO if_ex_ibapi_alm_ord_modify. STATICS sv_badiactive. * Konstante für BAdI-Referenzierung CONSTANTS lc_badiname TYPE exit_def VALUE 'IBAPI_ALM_ORD_MODIFY'. * start FLE MATNR BAPI Changes DATA: ls_fnames TYPE cl_matnr_chk_mapper=>ts_matnr_bapi_fnames, lt_fnames_hdr TYPE cl_matnr_chk_mapper=>tt_matnr_bapi_fname, lt_fnames_hdr_srv TYPE cl_matnr_chk_mapper=>tt_matnr_bapi_fname, lt_fnames_comp TYPE cl_matnr_chk_mapper=>tt_matnr_bapi_fname, lt_fnames_obj_list TYPE cl_matnr_chk_mapper=>tt_matnr_bapi_fname, lt_fnames_oper TYPE cl_matnr_chk_mapper=>tt_matnr_bapi_fname, lt_fnames_prt TYPE cl_matnr_chk_mapper=>tt_matnr_bapi_fname, lt_fnames_ref_ord_itm TYPE cl_matnr_chk_mapper=>tt_matnr_bapi_fname, lt_fnames_ref_ord_opr TYPE cl_matnr_chk_mapper=>tt_matnr_bapi_fname. DATA: lt_matnr_data_to_x_key_fnames TYPE cl_matnr_chk_mapper=>tt_matnr_data_to_x_key_fnames. DATA: lt_matnr_dta_2_xkey_fnames_hdr TYPE cl_matnr_chk_mapper=>tt_matnr_data_to_x_key_fnames. DATA: lt_mtnr_dta2xkey_fnames_hdrsrv TYPE cl_matnr_chk_mapper=>tt_matnr_data_to_x_key_fnames. DATA: lt_matnr_dta_2_xkey_fnames_opr TYPE cl_matnr_chk_mapper=>tt_matnr_data_to_x_key_fnames. DATA: lt_matnr_dta_2_xkey_fnames_cmp TYPE cl_matnr_chk_mapper=>tt_matnr_data_to_x_key_fnames. DATA: lt_mtnr_dta2xkey_fnames_rfoitm TYPE cl_matnr_chk_mapper=>tt_matnr_data_to_x_key_fnames. DATA: ls_matnr_data_to_x_key_fnames LIKE LINE OF lt_matnr_data_to_x_key_fnames. DATA: ls_matnr_data_to_x_line_ass TYPE cl_matnr_chk_mapper=>ts_matnr_data_to_x_line_ass. DATA: lt_matnr_data_to_x_line_ass TYPE cl_matnr_chk_mapper=>tt_matnr_data_to_x_line_ass. DATA: lv_linecount_data TYPE i. DATA: lv_linecount_data_up TYPE i. * MATERIAL CLEAR ls_fnames. ls_fnames-int = 'MATERIAL'. ls_fnames-ext = 'MATERIAL_EXTERNAL'. ls_fnames-vers = 'MATERIAL_VERSION'. ls_fnames-guid = 'MATERIAL_GUID'. ls_fnames-long = 'MATERIAL_LONG'. INSERT ls_fnames INTO TABLE lt_fnames_prt. ls_fnames-int_x = 'MATERIAL'. ls_fnames-ext_x = 'MATERIAL'. "no update flag existing, flag of internal field is used ls_fnames-vers_x = 'MATERIAL'. "no update flag existing, flag of internal field is used * ls_fnames-guid_x = 'MATERIAL_GUID'. ls_fnames-long_x = 'MATERIAL_LONG'. INSERT ls_fnames INTO TABLE lt_fnames_hdr. INSERT ls_fnames INTO TABLE lt_fnames_hdr_srv. INSERT ls_fnames INTO TABLE lt_fnames_comp. * ASSEMBLY CLEAR ls_fnames. ls_fnames-int = 'ASSEMBLY'. ls_fnames-ext = 'ASSEMBLY_EXTERNAL'. ls_fnames-vers = 'ASSEMBLY_VERSION'. ls_fnames-guid = 'ASSEMBLY_GUID'. ls_fnames-long = 'ASSEMBLY_LONG'. INSERT ls_fnames INTO TABLE lt_fnames_ref_ord_opr. INSERT ls_fnames INTO TABLE lt_fnames_obj_list. ls_fnames-int_x = 'ASSEMBLY'. ls_fnames-ext_x = 'ASSEMBLY'. "no update flag existing, flag of internal field is used ls_fnames-vers_x = 'ASSEMBLY'. "no update flag existing, flag of internal field is used * ls_fnames-guid_x = 'ASSEMBLY_GUID'. ls_fnames-long_x = 'ASSEMBLY_LONG'. INSERT ls_fnames INTO TABLE lt_fnames_hdr. INSERT ls_fnames INTO TABLE lt_fnames_oper. * SERMAT CLEAR ls_fnames. ls_fnames-int = 'SERMAT'. ls_fnames-ext = 'SERMAT_EXTERNAL'. ls_fnames-vers = 'SERMAT_VERSION'. ls_fnames-guid = 'SERMAT_GUID'. ls_fnames-long = 'SERMAT_LONG'. * ls_fnames-int_x = 'SERMAT'. * ls_fnames-ext_x = 'SERMAT_EXTERNAL'. * ls_fnames-vers_x = 'SERMAT_VERSION'. * ls_fnames-guid_x = 'SERMAT_GUID'. * ls_fnames-long_x = 'SERMAT_LONG'. INSERT ls_fnames INTO TABLE lt_fnames_obj_list. * MATERIAL_TO CLEAR ls_fnames. ls_fnames-int = 'MATERIAL_TO'. ls_fnames-ext = 'MATERIAL_TO_EXTERNAL'. ls_fnames-vers = 'MATERIAL_TO_VERSION'. ls_fnames-guid = 'MATERIAL_TO_GUID'. ls_fnames-long = 'MATERIAL_TO_LONG'. ls_fnames-int_x = 'MATERIAL_TO'. ls_fnames-ext_x = 'MATERIAL_TO'. "no update flag existing, flag of internal field is used ls_fnames-vers_x = 'MATERIAL_TO'. "no update flag existing, flag of internal field is used * ls_fnames-guid_x = 'MATERIAL_TO_GUID'. ls_fnames-long_x = 'MATERIAL_TO_LONG'. INSERT ls_fnames INTO TABLE lt_fnames_ref_ord_itm. * IT_HEADER CLEAR ls_matnr_data_to_x_key_fnames. ls_matnr_data_to_x_key_fnames-data_key_field = 'ORDERID'. ls_matnr_data_to_x_key_fnames-x_key_field = 'ORDERID'. APPEND ls_matnr_data_to_x_key_fnames TO lt_matnr_dta_2_xkey_fnames_hdr. cl_matnr_chk_mapper=>bapi_tables_conv_tab_x_names( EXPORTING iv_int_to_external = abap_false it_fnames = lt_fnames_hdr it_matnr_data_to_x_key_fnames = lt_matnr_dta_2_xkey_fnames_hdr CHANGING ct_matnr = it_header[] ct_matnrx = it_header_up[] EXCEPTIONS excp_matnr_ne = 1 excp_matnr_invalid_input = 2 OTHERS = 3 ). IF sy-subrc NE 0. CALL METHOD cl_matnr_chk_mapper=>bapi_get_last_error IMPORTING ev_return = ls_return. APPEND ls_return TO return. IF ls_return-type NA 'SIW'. RETURN. ENDIF. ENDIF. * IT_HEADER_SRV - No key fields DESCRIBE TABLE it_header_srv[] LINES lv_linecount_data. DESCRIBE TABLE it_header_srv_up[] LINES lv_linecount_data_up. CLEAR lt_matnr_data_to_x_line_ass[]. IF lv_linecount_data = lv_linecount_data_up. lv_linecount_data = 0. WHILE lv_linecount_data LT lv_linecount_data_up. ADD 1 TO lv_linecount_data. ls_matnr_data_to_x_line_ass-ass_x_line_idx = lv_linecount_data. ls_matnr_data_to_x_line_ass-data_line_idx = lv_linecount_data. APPEND ls_matnr_data_to_x_line_ass TO lt_matnr_data_to_x_line_ass. ENDWHILE. ENDIF. cl_matnr_chk_mapper=>bapi_tables_conv_tab_x_idx( EXPORTING iv_int_to_external = abap_false it_fnames = lt_fnames_hdr_srv it_matnr_data_to_x_line_ass = lt_matnr_data_to_x_line_ass CHANGING ct_matnr = it_header_srv[] ct_matnrx = it_header_srv_up[] EXCEPTIONS excp_matnr_ne = 1 excp_matnr_invalid_input = 2 OTHERS = 3 ). IF sy-subrc NE 0. CALL METHOD cl_matnr_chk_mapper=>bapi_get_last_error IMPORTING ev_return = ls_return. APPEND ls_return TO return. IF ls_return-type NA 'SIW'. RETURN. ENDIF. ENDIF. * IT_OPERATION - No key fields * DESCRIBE TABLE it_operation[] LINES lv_linecount_data. * DESCRIBE TABLE it_operation_up[] LINES lv_linecount_data_up. * CLEAR lt_matnr_data_to_x_line_ass[]. * IF lv_linecount_data = lv_linecount_data_up. * lv_linecount_data = 0. * WHILE lv_linecount_data LT lv_linecount_data_up. * ADD 1 TO lv_linecount_data. * ls_matnr_data_to_x_line_ass-ass_x_line_idx = lv_linecount_data. * ls_matnr_data_to_x_line_ass-data_line_idx = lv_linecount_data. * APPEND ls_matnr_data_to_x_line_ass TO lt_matnr_data_to_x_line_ass. * ENDWHILE. * ENDIF. CLEAR lt_matnr_data_to_x_line_ass[]. LOOP AT it_operation_up. READ TABLE it_operation INDEX sy-tabix TRANSPORTING NO FIELDS. IF sy-subrc IS INITIAL. ls_matnr_data_to_x_line_ass-ass_x_line_idx = sy-tabix. ls_matnr_data_to_x_line_ass-data_line_idx = sy-tabix. APPEND ls_matnr_data_to_x_line_ass TO lt_matnr_data_to_x_line_ass. ENDIF. ENDLOOP. cl_matnr_chk_mapper=>bapi_tables_conv_tab_x_idx( EXPORTING iv_int_to_external = abap_false it_fnames = lt_fnames_oper it_matnr_data_to_x_line_ass = lt_matnr_data_to_x_line_ass CHANGING ct_matnr = it_operation[] ct_matnrx = it_operation_up[] EXCEPTIONS excp_matnr_ne = 1 excp_matnr_invalid_input = 2 OTHERS = 3 ). IF sy-subrc NE 0. CALL METHOD cl_matnr_chk_mapper=>bapi_get_last_error IMPORTING ev_return = ls_return. APPEND ls_return TO return. IF ls_return-type NA 'SIW'. RETURN. ENDIF. ENDIF. * IT_COMPONENT - No key fields * DESCRIBE TABLE it_component[] LINES lv_linecount_data. * DESCRIBE TABLE it_component_up[] LINES lv_linecount_data_up. * CLEAR lt_matnr_data_to_x_line_ass[]. * IF lv_linecount_data = lv_linecount_data_up. * lv_linecount_data = 0. * WHILE lv_linecount_data LT lv_linecount_data_up. * ADD 1 TO lv_linecount_data. * ls_matnr_data_to_x_line_ass-ass_x_line_idx = lv_linecount_data. * ls_matnr_data_to_x_line_ass-data_line_idx = lv_linecount_data. * APPEND ls_matnr_data_to_x_line_ass TO lt_matnr_data_to_x_line_ass. * ENDWHILE. * ENDIF. CLEAR lt_matnr_data_to_x_line_ass[]. LOOP AT it_component_up. READ TABLE it_component INDEX sy-tabix TRANSPORTING NO FIELDS. IF sy-subrc IS INITIAL. ls_matnr_data_to_x_line_ass-ass_x_line_idx = sy-tabix. ls_matnr_data_to_x_line_ass-data_line_idx = sy-tabix. APPEND ls_matnr_data_to_x_line_ass TO lt_matnr_data_to_x_line_ass. ENDIF. ENDLOOP. cl_matnr_chk_mapper=>bapi_tables_conv_tab_x_idx( EXPORTING iv_int_to_external = abap_false it_fnames = lt_fnames_comp it_matnr_data_to_x_line_ass = lt_matnr_data_to_x_line_ass CHANGING ct_matnr = it_component[] ct_matnrx = it_component_up[] EXCEPTIONS excp_matnr_ne = 1 excp_matnr_invalid_input = 2 OTHERS = 3 ). IF sy-subrc NE 0. CALL METHOD cl_matnr_chk_mapper=>bapi_get_last_error IMPORTING ev_return = ls_return. APPEND ls_return TO return. IF ls_return-type NA 'SIW'. RETURN. ENDIF. ENDIF. * IT_REFORDER_ITEM CLEAR ls_matnr_data_to_x_key_fnames. ls_matnr_data_to_x_key_fnames-data_key_field = 'ORDERID'. ls_matnr_data_to_x_key_fnames-x_key_field = 'ORDERID'. APPEND ls_matnr_data_to_x_key_fnames TO lt_mtnr_dta2xkey_fnames_rfoitm. cl_matnr_chk_mapper=>bapi_tables_conv_tab_x_names( EXPORTING iv_int_to_external = abap_false it_fnames = lt_fnames_ref_ord_itm it_matnr_data_to_x_key_fnames = lt_mtnr_dta2xkey_fnames_rfoitm CHANGING ct_matnr = it_reforder_item[] ct_matnrx = it_reforder_item_up[] EXCEPTIONS excp_matnr_ne = 1 excp_matnr_invalid_input = 2 OTHERS = 3 ). IF sy-subrc NE 0. CALL METHOD cl_matnr_chk_mapper=>bapi_get_last_error IMPORTING ev_return = ls_return. APPEND ls_return TO return. IF ls_return-type NA 'SIW'. RETURN. ENDIF. ENDIF. * IT_OBJECTLIST * No UP-structure with material field CALL METHOD cl_matnr_chk_mapper=>bapi_tables_conv_tab EXPORTING iv_int_to_external = abap_false it_fnames = lt_fnames_obj_list CHANGING ct_matnr = it_objectlist[] EXCEPTIONS excp_matnr_ne = 1 excp_matnr_invalid_input = 2 OTHERS = 3. IF sy-subrc NE 0. CALL METHOD cl_matnr_chk_mapper=>bapi_get_last_error IMPORTING ev_return = ls_return. APPEND ls_return TO return. IF ls_return-type NA 'SIW'. RETURN. ENDIF. ENDIF. * IT_PRT * No UP-structure with material field CALL METHOD cl_matnr_chk_mapper=>bapi_tables_conv_tab EXPORTING iv_int_to_external = abap_false it_fnames = lt_fnames_prt CHANGING ct_matnr = it_prt[] EXCEPTIONS excp_matnr_ne = 1 excp_matnr_invalid_input = 2 OTHERS = 3. IF sy-subrc NE 0. CALL METHOD cl_matnr_chk_mapper=>bapi_get_last_error IMPORTING ev_return = ls_return. APPEND ls_return TO return. IF ls_return-type NA 'SIW'. RETURN. ENDIF. ENDIF. * IT_REFORDER_OPERATION * No UP-structure CALL METHOD cl_matnr_chk_mapper=>bapi_tables_conv_tab EXPORTING iv_int_to_external = abap_false it_fnames = lt_fnames_ref_ord_opr CHANGING ct_matnr = it_reforder_operation[] EXCEPTIONS excp_matnr_ne = 1 excp_matnr_invalid_input = 2 OTHERS = 3. IF sy-subrc NE 0. CALL METHOD cl_matnr_chk_mapper=>bapi_get_last_error IMPORTING ev_return = ls_return. APPEND ls_return TO return. IF ls_return-type NA 'SIW'. RETURN. ENDIF. ENDIF. * end FLE MATNR BAPI Changes * Initialisierungen *************************************** * setzen BAPI-Flag z.B. für Prüfloserzeugung MOVE 'X' TO gv_bapi_flg. "note 1302002 * Memory refresh CALL FUNCTION 'IBAPI_PROC_INIT_REQUEST'. * Badi initialisieren IF sv_badiactive IS INITIAL. CALL METHOD cl_exithandler=>get_instance EXPORTING exit_name = lc_badiname null_instance_accepted = 'X' CHANGING instance = sr_modify_input_data. sv_badiactive = 'X'. ENDIF. * Retrunparemetertabellen löschen CLEAR return[]. CLEAR et_numbers[]. * globales Bapiflag setzen CALL FUNCTION 'IBAPI_Z_SET_BAPI_FLAG' EXPORTING iv_flag = 'X'. CALL FUNCTION 'DIALOG_GET_STATUS' "Note 1441350 IMPORTING "Note 1441350 dialog_status = gv_dialog. "Note 1441350 CALL FUNCTION 'DIALOG_SET_NO_DIALOG'. "Note 1441350 * Aktionsbuffer für Auftragskopfdaten CALL FUNCTION 'IBAPI_ALM_ORDER_INIT_ACTIONS'. * Application Log initialisieren PERFORM alm_order_msg_log_init. * Tabelle mit Methoden kopieren MOVE it_methods[] TO lt_methods. * start of note 1837200 * usage of method DIALOG together with MMSRV is not supported READ TABLE lt_methods TRANSPORTING NO FIELDS WITH KEY method = 'DIALOG'. IF sy-subrc = 0. LOOP AT lt_methods ASSIGNING <fs_methods> WHERE objecttype CS 'SERVICE'. MESSAGE e137(iwo_bapi2) WITH <fs_methods>-objecttype INTO mess. bapi_message. MESSAGE e113(iwo_bapi2) INTO mess. bapi_message. PERFORM end_bapi CHANGING return[]. PERFORM reset_created_headers USING et_numbers[] lt_method_level. RETURN. ENDLOOP. ENDIF. * end of note 1837200 * Schnittstellendaten in interne Strukturen umwandeln ***** CALL FUNCTION 'IBAPI_PROC_INTERFACE_E2I' EXPORTING it_header = it_header[] it_header_up = it_header_up[] it_header_srv = it_header_srv[] it_header_srv_up = it_header_srv_up[] it_userstatus = it_userstatus[] it_partner = it_partner[] it_partner_up = it_partner_up[] it_operation = it_operation[] it_operation_up = it_operation_up[] it_relation = it_relation[] it_relation_up = it_relation_up[] it_component = it_component[] it_component_up = it_component_up[] it_objectlist = it_objectlist[] it_objectlist_up = it_objectlist_up[] it_olist_relation = it_olist_relation[] it_srule = it_srule[] it_srule_up = it_srule_up[] it_text = it_text[] it_text_lines = it_text_lines[] it_tasklists = it_tasklists[] it_reforder_item = it_reforder_item[] it_reforder_item_up = it_reforder_item_up[] it_reforder_operation = it_reforder_operation[] it_reforder_serno_olist_ins = it_reforder_serno_olist_ins[] it_reforder_serno_olist_del = it_reforder_serno_olist_del[] it_serviceoutline = it_serviceoutline[] it_servicelines = it_servicelines[] it_servicelimit = it_servicelimit[] it_servicecontractlimits = it_servicecontractlimits[] it_serviceoutline_up = it_serviceoutline_up[] it_servicelines_up = it_servicelines_up[] it_servicelimit_up = it_servicelimit_up[] it_servicecontractlimits_up = it_servicecontractlimits_up[] it_permit = it_permit[] it_permit_up = it_permit_up[] it_permit_issue = it_permit_issue[] it_estimated_costs = it_estimated_costs[] " 1672966 EAMCC PM110 it_header_jva = it_header_jva[] it_header_jva_up = it_header_jva_up[] it_text_add = it_additional_text[] "note 2756658 IMPORTING et_caufvd = lt_caufvd et_caufvd_up = lt_caufvd_up et_caufvd_srv = lt_pmsdo et_caufvd_srv_up = lt_pmsdo_up et_userstatus = lt_userstatus et_partner = lt_partner et_partner_up = lt_partner_up et_afvgd = lt_afvgd et_afvgd_up = lt_afvgd_up et_afabd = lt_afabd et_afabd_up = lt_afabd_up et_resbd = lt_resbd et_resbd_up = lt_resbd_up et_riwol = lt_riwol et_riwol_up = lt_riwol_up et_olist_relation = lt_olist_relation et_cobl = lt_cobl et_cobl_up = lt_cobl_up et_thead = lt_text et_tlines = lt_text_lines et_tasklists = lt_tasklists et_afpod = lt_afpod et_afpod_up = lt_afpod_up et_afpod_resbd = lt_afpod_resbd et_afpod_resbd_up = lt_afpod_resbd_up et_reford_afvgd = lt_reford_afvgd et_serno_olist_ins = lt_serno_olist_ins et_serno_olist_del = lt_serno_olist_del et_serviceoutline = lt_serviceoutline et_servicelines = lt_servicelines et_servicelimit = lt_servicelimit et_servicecontractlimits = lt_servicecontractlimits et_serviceoutline_up = lt_serviceoutline_up et_servicelines_up = lt_servicelines_up et_servicelimit_up = lt_servicelimit_up et_servicecontractlimits_up = lt_servicecontractlimits_up et_permit = lt_permit et_permit_up = lt_permit_up et_permit_issue = lt_permit_issue et_estimated_costs = lt_est_cost " 1672966 EAMCC PM110 et_thead_add = lt_text_add "note 2756658 et_settlement_profile = lt_settlmt_profile EXCEPTIONS conversion_error = 1 textline_error = 2 OTHERS = 3. IF sy-subrc NE 0. PERFORM end_bapi CHANGING return[]. EXIT. ENDIF. *--- fill PRT data in int. tables (mapping is performed later) lt_prt = it_prt[]. lt_prt_up = it_prt_up[]. * BADI zum prüfen und ändern der Eingabedaten ************* * aufrufen. Zu diesem Zeitpunkt sind die meisten ********** * Daten im internen Format verfügbar ********************** IF NOT sr_modify_input_data IS INITIAL. * Abwärtskompatibilität: In frühen Versionen wurden nur die externen * Repräsentationen der Auftragskopfdaten angeboten. Dabei können nur * bestimmte Teile der Auftragsköpfe geändert werden. Falls aber Kunden * bereits eine entsprechende BAdI-Implementation erstellt haben, wird * Nacharbeit notwendig, um die alte Logik nach wie vor zu * unterstützen LOOP AT it_header. MOVE-CORRESPONDING it_header TO ls_bapihead. APPEND ls_bapihead TO lt_bapihead. ENDLOOP. LOOP AT it_header_up. MOVE-CORRESPONDING it_header_up TO ls_bapihead_up. APPEND ls_bapihead_up TO lt_bapihead_up. ENDLOOP. LOOP AT it_header_srv. MOVE-CORRESPONDING it_header_srv TO ls_bapisrvcdata. MOVE it_header_srv-material_long TO ls_bapisrvcdata-material. "MFLE APPEND ls_bapisrvcdata TO lt_bapisrvcdata. ENDLOOP. LOOP AT it_header_srv_up. MOVE-CORRESPONDING it_header_srv_up TO ls_bapisrvcdata_up. MOVE it_header_srv_up-material_long TO ls_bapisrvcdata_up-material. "MFLE APPEND ls_bapisrvcdata_up TO lt_bapisrvcdata_up. ENDLOOP. * Before-Image für externe Datenrepräsentation sichern lt_bapihead_old = lt_bapihead. lt_bapihead_old_up = lt_bapihead_up. lt_bapisrvcdata_old = lt_bapisrvcdata. lt_bapisrvcdata_old_up = lt_bapisrvcdata_up. CLEAR lt_extension_up. " Note 1989741 cl_im_eams_ord_cfd_write=>extension_in_tab = extension_in[]. LOOP AT extension_in. CALL METHOD sr_modify_input_data->modify_input_data EXPORTING extension_in = extension_in CHANGING ct_methods = lt_methods ct_header = lt_bapihead ct_header_up = lt_bapihead_up ct_header_srv = lt_bapisrvcdata ct_header_srv_up = lt_bapisrvcdata_up ct_userstatus = lt_userstatus ct_partner = lt_partner ct_partner_up = lt_partner_up ct_operation = lt_afvgd ct_operation_up = lt_afvgd_up ct_relation = lt_afabd ct_relation_up = lt_afabd_up ct_component = lt_resbd ct_component_up = lt_resbd_up ct_objectlist = lt_riwol ct_text = lt_text ct_text_lines = lt_text_lines ct_messages = lt_messages ct_header_int = lt_caufvd ct_header_int_up = lt_caufvd_up ct_pmsdo_srv = lt_pmsdo ct_pmsdo_srv_up = lt_pmsdo_up ct_reforder_item_int = lt_afpod ct_reforder_item_int_up = lt_afpod_up ct_reforder_comp = lt_afpod_resbd ct_reforder_comp_up = lt_afpod_resbd_up ct_reforder_serno_olist_ins = lt_serno_olist_ins ct_reforder_serno_olist_del = lt_serno_olist_del ct_prt = lt_prt ct_prt_up = lt_prt_up ct_serviceoutline = lt_serviceoutline ct_serviceoutline_up = lt_serviceoutline_up ct_servicelines = lt_servicelines ct_servicelines_up = lt_servicelines_up ct_servicelimit = lt_servicelimit ct_servicelimit_up = lt_servicelimit_up ct_servicecontractlimits = lt_servicecontractlimits ct_servicecontractlimits_up = lt_servicecontractlimits_up ct_estimated_costs = lt_est_cost. " 1672966 EAMCC PM110 * Note 1989741 - begin IF extension_in-structure IS NOT INITIAL. ls_extension_up-fieldname = extension_in-structure. ls_extension_up-bapiupdate = 'X'. APPEND ls_extension_up TO lt_extension_up. ENDIF. * Note 1989741 - end ENDLOOP. * Before- und After-Image für alte Logik vergleichen: * Bei Delta nur die externe Repräsentation der Kopfdaten verwenden IF lt_bapihead_old <> lt_bapihead OR lt_bapihead_old_up <> lt_bapihead_up OR lt_bapisrvcdata_old <> lt_bapisrvcdata OR lt_bapisrvcdata_old_up <> lt_bapisrvcdata_up. * Aus im BAdI veränderten Daten Import-Daten wiederherstellen, * Konvertierung für Kopfdaten erneut durchführen LOOP AT lt_bapihead INTO ls_bapihead. MOVE-CORRESPONDING ls_bapihead TO ls_header. APPEND ls_header TO lt_header. ENDLOOP. LOOP AT lt_bapihead_up INTO ls_bapihead_up. MOVE-CORRESPONDING ls_bapihead_up TO ls_header_up. APPEND ls_header_up TO lt_header_up. ENDLOOP. LOOP AT lt_bapisrvcdata INTO ls_bapisrvcdata. MOVE-CORRESPONDING ls_bapisrvcdata TO ls_header_srv. ls_header_srv-material_long = ls_bapisrvcdata-material. "MFLE CLEAR: ls_header_srv-material. "MFLE APPEND ls_header_srv TO lt_header_srv. ENDLOOP. LOOP AT lt_bapisrvcdata_up INTO ls_bapisrvcdata_up. MOVE-CORRESPONDING ls_bapisrvcdata_up TO ls_header_srv_up. ls_header_srv_up-material_long = ls_bapisrvcdata_up-material. "MFLE APPEND ls_header_srv_up TO lt_header_srv_up. ENDLOOP. CALL FUNCTION 'IBAPI_PROC_INTERFACE_E2I' EXPORTING it_header = lt_header[] it_header_up = lt_header_up[] it_header_srv = lt_header_srv[] it_header_srv_up = lt_header_srv_up[] it_userstatus = it_userstatus[] it_partner = it_partner[] it_operation = it_operation[] it_relation = it_relation[] it_component = it_component[] it_text = it_text[] it_text_lines = it_text_lines[] IMPORTING et_caufvd = lt_caufvd et_caufvd_up = lt_caufvd_up et_caufvd_srv = lt_pmsdo et_caufvd_srv_up = lt_pmsdo_up EXCEPTIONS conversion_error = 1 textline_error = 2 OTHERS = 3. IF sy-subrc NE 0. PERFORM end_bapi CHANGING return[]. EXIT. ENDIF. ENDIF. ENDIF. * Messages vom BADI auswerten und ins BAPI-Log scheiben * Fehler in Tabelle RETURN schreiben. * Bei Message E oder A bricht der Bapi ab CLEAR return[]. LOOP AT lt_messages INTO ls_messages. CALL FUNCTION 'BALW_BAPIRETURN_GET2' EXPORTING type = ls_messages-msgty cl = ls_messages-msgid number = ls_messages-msgno par1 = ls_messages-msgv1 par2 = ls_messages-msgv2 par3 = ls_messages-msgv3 par4 = ls_messages-msgv4 IMPORTING return = ls_return. APPEND ls_return TO return[]. IF ls_messages-msgty CA 'AE'. MOVE 4 TO lv_error. ENDIF. ENDLOOP. "Message-Log zurückgeben IF lv_error NE 0. EXIT. ENDIF. * Prüfen, ob der Trace geschrieben werden soll, * und ihn dann auf das Frontend schreiben. Dies * geht natürlich nur, wenn der BAPI vom Frontend * aus aufgerufen wird. * Der Trace kann auch dazu dienen festzustellen, ob die * Daten korrekt kovertiert wurden, und der BADI das * richtige gemacht hat. CALL FUNCTION 'IBAPI_PROC_SAVE_TRACE' EXPORTING it_header = lt_caufvd it_header_up = lt_caufvd_up it_header_srv = lt_pmsdo it_header_srv_up = lt_pmsdo_up it_userstatus = lt_userstatus it_partner = lt_partner it_partner_up = lt_partner_up it_operation = lt_afvgd it_operation_up = lt_afvgd_up it_relation = lt_afabd it_relation_up = lt_afabd_up it_component = lt_resbd it_component_up = lt_resbd_up it_objectlist = lt_riwol it_srule = lt_cobl it_srule_up = lt_cobl_up it_text = lt_text it_text_lines = lt_text_lines it_tasklists = lt_tasklists CHANGING ct_methods = lt_methods. * Methodentabelle auf Konsistenz prüfen und in internes * Format umsetzen. Bestimmen, welche Aufträge in die * Belegtabelle gelesen werden müssen. CALL FUNCTION 'IBAPI_PROC_METHOD_TABLE_E2I' IMPORTING et_orders = lt_orders CHANGING ct_method_table = lt_methods EXCEPTIONS object_unknown = 1 method_unknown = 2 invalid_order_key = 3 required_order_no_created = 4 save_or_dialog_required = 5 OTHERS = 6. IF sy-subrc NE 0. * Fehler werden bereits in FB geloggt * setzen des Fehlerflags und verlassen des Bapis PERFORM end_bapi CHANGING return[]. EXIT. ENDIF. * Reihenfolge der Bearbeitung festlegen. ****************** * dies ist vor allem dann wichtig, wenn ******************* * Anordnungsbeziehungen zwischen neu ********************** * angelegten Vorgängen erzeugt werden sollen. ************* CALL FUNCTION 'IBAPI_SET_METHOD_LEVEL' EXPORTING it_methods = lt_methods IMPORTING et_method_level = lt_method_level. * Lesen der Aufträge in die Belegtabellen und sperren. CALL FUNCTION 'IBAPI_READ_AND_LOCK_ORDERS' EXPORTING it_aufnr = lt_orders it_methods = lt_methods EXCEPTIONS order_not_found = 1 release_no_change = 2 order_locked = 3 OTHERS = 4. IF sy-subrc NE 0. * Fehler beim Lesen der Aufträge in die Belegtabellen PERFORM end_bapi CHANGING return[]. EXIT. ENDIF. * For supporting geospatial data processing,the code related to note 2550268 is disabled **-- check orders is geo enabled note 2550268 * PERFORM eamgef_order_check USING it_header[] * lt_method_level * CHANGING lv_error. * IF lv_error NE 0. * PERFORM end_bapi CHANGING return[]. * EXIT. * ENDIF. "note 2550268 * For supporting geospatial data processing,the code related to note 2550268 is disabled * Linear Asset Management EhP5 IF cl_ops_switch_check=>eam_sfws_lfe( ) IS NOT INITIAL. CALL METHOD cl_eaml_ea_bapi_util=>set_order_data_buf EXPORTING it_header = it_header[] it_header_up = it_header_up[] it_operation = it_operation[] it_operation_up = it_operation_up[]. ENDIF. * >>>>> Begin note 2304265: DFPS specific checks clear lv_method_del. if cl_check_switch=>dfps_is_active( ) = abap_true. perform dfps_auth_check tables it_header return changing lt_method_level lv_method_del. endif. if lv_method_del = abap_true. * At least one method was deleted by the DFPS change protection checks, therefore it will be checked in the following * if only a save method remains in the processing methods. If yes, this save must no longer be processed. if lines( lt_method_level ) = 1. read table lt_method_level transporting no fields with key method = if_eams_bo_const=>gc_bapi_ord_method-save. if sy-subrc = 0. * only a save method exists ==> delete this method too clear lt_method_level. endif. endif. endif. if lt_method_level is not initial. * <<<<< End note 2304265 * Ausführen der in der Methodentabelle hinterlegten ******* * Methoden ************************************************ CALL FUNCTION 'IBAPI_PROC_METHOD_TABLE_EXEC' EXPORTING it_proc_level_tab = lt_method_level it_order_tab = lt_caufvd it_order_up_tab = lt_caufvd_up it_order_srv_tab = lt_pmsdo it_order_srv_up_tab = lt_pmsdo_up it_userstatus_tab = lt_userstatus it_partner_tab = lt_partner it_partner_up_tab = lt_partner_up it_operation_tab = lt_afvgd it_operation_up_tab = lt_afvgd_up it_relation_tab = lt_afabd it_relation_up_tab = lt_afabd_up it_component_tab = lt_resbd it_component_up_tab = lt_resbd_up it_objectlist_tab = lt_riwol it_objectlist_up_tab = lt_riwol_up it_olist_relation_tab = lt_olist_relation it_cobl_tab = lt_cobl it_cobl_up_tab = lt_cobl_up it_text_tab = lt_text it_text_lines_tab = lt_text_lines it_tasklists = lt_tasklists it_extension_up = lt_extension_up " Note 1989741 it_reforder_item = lt_afpod it_reforder_item_up = lt_afpod_up it_reforder_comp = lt_afpod_resbd it_reforder_comp_up = lt_afpod_resbd_up it_reforder_operation = lt_reford_afvgd it_reforder_serno_olist_ins = lt_serno_olist_ins it_reforder_serno_olist_del = lt_serno_olist_del it_prt = lt_prt it_prt_up = lt_prt_up it_serviceoutline = lt_serviceoutline it_serviceoutline_up = lt_serviceoutline_up it_servicelines = lt_servicelines it_servicelines_up = lt_servicelines_up it_servicelimit = lt_servicelimit it_servicelimit_up = lt_servicelimit_up it_servicecontractlimits = lt_servicecontractlimits it_servicecontractlimits_up = lt_servicecontractlimits_up it_permit = lt_permit it_permit_up = lt_permit_up it_permit_issue = lt_permit_issue iv_mmsrv_external_maintenace = iv_mmsrv_external_maintenace it_estimated_costs = lt_est_cost " 1672966 EAMCC PM110 it_text_add_tab = lt_text_add "note 2756658 it_settlmt_profile = lt_settlmt_profile IMPORTING et_numbers = et_numbers[] et_notif_numbers = et_notification_numbers[] EXCEPTIONS data_for_method_not_found = 1 method_not_supported = 2 error_in_processing = 3 OTHERS = 4. IF sy-subrc NE 0. * Fehler &1 beim Bearbeiten der Bapi-Methoden MESSAGE e113(iwo_bapi2) INTO mess. bapi_message. * New with ERP 2005: If order headers are created BUT subsequent objects * led to an error, the order header update flag is now set to 'IGNORE' for * update processes. PERFORM reset_created_headers USING et_numbers[] lt_method_level. PERFORM end_bapi CHANGING return[]. EXIT. ENDIF. endif. "DFPS note 2304265 * Lesen des Application Logs und zurückgeben der ********** * Meldungen in die Exporttabelle ************************** PERFORM end_bapi CHANGING return[]. ENHANCEMENT-POINT bapi_alm_order_maintain_g7 SPOTS es_saplibapi_alm_order. ENDFUNCTION.
09-04
非常感谢你提供完整的 `BAPI_ALM_ORDER_MAINTAIN` 源代码!我们可以**从源码角度深入分析**你遇到的问题:“输入一个作业号”错误。 --- ## ✅ 问题回顾 你遇到的错误是: > 输入一个作业号("Input an order number") 虽然你确认: - `aufnr` 是有前导零的,格式正确; - `IW2K` 可以正常编辑组件; - 已传入 `it_header`、`it_component`、`it_methods` 等; - 已调用 `BAPI_TRANSACTION_COMMIT`; - 但调用 `BAPI_ALM_ORDER_MAINTAIN` 仍然报错。 --- ## ✅ 从源码中定位关键点 我们从源码中找到几个**关键函数模块**和**关键逻辑段落**来分析错误来源。 --- ### 🔍 1. `IBAPI_PROC_METHOD_TABLE_E2I` 函数模块 这个函数负责将 `it_methods` 表转换为内部格式,并校验订单号是否有效。 #### 关键逻辑: ```abap CALL FUNCTION 'IBAPI_PROC_METHOD_TABLE_E2I' IMPORTING et_orders = lt_orders CHANGING ct_method_table = lt_methods EXCEPTIONS object_unknown = 1 method_unknown = 2 invalid_order_key = 3 ← 重点异常 required_order_no_created = 4 save_or_dialog_required = 5 OTHERS = 6. ``` #### 说明: - 如果订单号无效或不存在,会触发 `invalid_order_key = 3` 异常。 - 即使你在 `IW2K` 中可以访问订单,也可能因为权限或系统上下文不同导致 BAPI 无法识别。 #### ✅ 建议: - 检查 `it_methods` 中的 `orderid` 是否与 `aufnr` 完全一致; - 检查订单是否被锁定(如通过其他事务); - 使用 `ST22` 查看是否触发了这个异常。 --- ### 🔍 2. `IBAPI_READ_AND_LOCK_ORDERS` 函数模块 这个函数负责从数据库中读取并锁定订单。 ```abap CALL FUNCTION 'IBAPI_READ_AND_LOCK_ORDERS' EXPORTING it_aufnr = lt_orders it_methods = lt_methods EXCEPTIONS order_not_found = 1 ← 重点异常 release_no_change = 2 order_locked = 3 OTHERS = 4. ``` #### 说明: - 如果订单号在数据库中找不到,会触发 `order_not_found = 1`。 - 即使订单存在,如果用户权限不足或订单状态不允许修改,也会触发异常。 #### ✅ 建议: - 使用事务码 `SU53` 检查用户权限; - 检查订单状态是否为“已关闭”、“已释放”等不可编辑状态; - 使用 `SE37` 手动传入 `it_methods` 和 `it_header` 测试。 --- ### 🔍 3. `it_methods` 中的 `ORDERID` 校验 在 `IBAPI_PROC_INTERFACE_E2I` 函数中,`it_methods` 中的 `ORDERID` 会被用于构建内部结构。 ```abap READ TABLE lt_methods TRANSPORTING NO FIELDS WITH KEY method = 'DIALOG'. ``` #### 说明: - 如果 `it_methods` 中没有包含 `SAVE` 方法,或 `ORDERID` 为空,会导致内部结构构建失败。 - `ORDERID` 必须与 `it_header` 和 `it_component` 中的 `ORDERID` 完全一致。 #### ✅ 建议: - 确保 `it_methods` 中每个条目都有正确的 `ORDERID`; - 确保 `SAVE` 方法在最后执行; - 所有 `ORDERID` 字段必须一致。 --- ### 🔍 4. `BAPI_PROC_INTERFACE_E2I` 接口转换错误 这个函数负责将外部结构(如 `it_header`, `it_component`)转换为内部结构。 ```abap IF sy-subrc NE 0. PERFORM end_bapi CHANGING return[]. EXIT. ENDIF. ``` #### 说明: - 如果转换失败,会直接退出 BAPI,且不会返回具体错误信息; - 常见原因包括字段类型不匹配、字段长度不一致、字段值非法等。 #### ✅ 建议: - 检查 `it_header` 中字段是否完整(如 `ORDER_TYPE`, `PLANPLANT`, `MAINTPLANT`); - 检查 `it_component` 中是否有非法字段值(如空 `MATERIAL`); - 使用 `SE37` 手动调试,查看哪个字段导致转换失败。 --- ## ✅ 最终建议解决方案 ### ✅ 1. 检查 `it_methods` 是否完整 ```abap data: ls_method type bapi_alm_order_method. " 添加组件 ls_method-refnumber = '000010'. ls_method-objecttype = 'COMP'. ls_method-method = 'ADD'. ls_method-orderid = aufnr. append ls_method to it_methods. " 保存订单 ls_method-refnumber = '000000'. ls_method-objecttype = 'HEADER'. ls_method-method = 'SAVE'. ls_method-orderid = aufnr. append ls_method to it_methods. ``` > ✅ `SAVE` 方法必须存在且放在最后! --- ### ✅ 2. 检查 `it_header` 是否完整 ```abap data: ls_header type bapi_alm_order_headers_i. ls_header-orderid = aufnr. ls_header-order_type = 'PM01'. " 订单类型必须与原订单一致 ls_header-planplant = '1000'. " 计划工厂 ls_header-maintplant = '1000'. " 维护工厂 append ls_header to it_header. ``` --- ### ✅ 3. 检查 `it_component` 是否完整 ```abap data: ls_component type bapi_alm_order_components_i. ls_component-refnumber = '000010'. ls_component-position = '10'. ls_component-material = 'MAT12345'. ls_component-quantity = '1'. ls_component-base_uom = 'EA'. ls_component-orderid = aufnr. append ls_component to it_component. ``` --- ### ✅ 4. 检查 `it_component_up` 是否有更新标志 ```abap data: ls_component_up type bapi_alm_order_components_up_i. ls_component_up-refnumber = '000010'. ls_component_up-updateindicator = 'U'. append ls_component_up to it_component_up. ``` --- ### ✅ 5. 使用 `SE37` 手动测试 1. 打开事务码 `SE37`; 2. 输入 `BAPI_ALM_ORDER_MAINTAIN`; 3. 在 `Tables` 标签页中手动传入 `it_methods`, `it_header`, `it_component`; 4. 执行函数,查看 `return` 表的详细错误信息。 --- ## ✅ 总结 | 项目 | 建议 | |------|------| | `it_methods` | 必须包含 `SAVE`,`ORDERID` 必须一致 | | `it_header` | 必须填写完整字段(如 `ORDER_TYPE`, `PLANPLANT`) | | `it_component` | `REFNUMBER` 和 `POSITION` 必须正确 | | `it_component_up` | 必须包含 `UPDATEINDICATOR = 'U'` | | `SE37` 调试 | 手动传入参数,查看详细错误 | | `ST22` | 查看运行时日志,定位异常位置 | --- ###
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值