欢迎来到萧静默的博客

书山有路勤为径,学海无涯苦作舟。

SAP采购订单保存增强

SAP采购订单保存增强,可以使用的比较多,badi找到两种ME_PROCESS_PO_CUST/ME_PURCHDOC_POSTED。

第一次使用的是ME_PURCHDOC_POSTED,里面方法就一个

image

 做自定义增强后,可以在方法里面写代码,比如下面做的一个是根据公司及订单类型控制订单修改后的数量不能超过原来的订单数量

IF SY-TCODE = 'ME22N'.
      TYPES:BEGIN OF TY_DATA,
              MATNR TYPE EKPO-MATNR,
              MENGE TYPE EKPO-MENGE,
            END OF TY_DATA.
      DATA:LT_DATA_OLD TYPE TABLE OF TY_DATA,
           LS_DATA_OLD TYPE TY_DATA.
      DATA:LT_DATA_NEW TYPE TABLE OF TY_DATA,
           LS_DATA_NEW TYPE TY_DATA.

      DATA:LS_HEAD TYPE  MEPOHEADER.

      MOVE-CORRESPONDING IM_EKKO TO LS_HEAD.
      IF ( LS_HEAD-BUKRS = '1010' OR LS_HEAD-BUKRS = '1030' ) AND LS_HEAD-BSART = 'LNB'.
        "合计原订单各物料数量
        LOOP AT IM_EKPO_OLD INTO DATA(LS_EKPO_OLD) WHERE ELIKZ <> 'X'.
          MOVE-CORRESPONDING LS_EKPO_OLD TO LS_DATA_OLD.
          COLLECT LS_DATA_OLD INTO LT_DATA_OLD.
          CLEAR:LS_EKPO_OLD,LS_DATA_OLD.
        ENDLOOP.
        "合计修改后订单各物料数量
        LOOP AT IM_EKPO INTO DATA(LS_EKPO_NEW).
          MOVE-CORRESPONDING LS_EKPO_NEW TO LS_DATA_NEW.
          COLLECT LS_DATA_NEW INTO LT_DATA_NEW.
          CLEAR:LS_EKPO_NEW,LS_DATA_NEW.
        ENDLOOP.

        LOOP AT LT_DATA_NEW INTO LS_DATA_NEW.
          READ TABLE LT_DATA_OLD INTO LS_DATA_OLD WITH KEY MATNR = LS_DATA_NEW-MATNR.
          IF LS_DATA_NEW-MENGE > LS_DATA_OLD-MENGE.
            MESSAGE E001(ZMM01) .
          ENDIF.
        ENDLOOP.
      ENDIF.
    ENDIF.

可以有效果

image

 但是点勾后会有报错,并且离开屏幕,没弄清楚是啥原因。

image

 所以这里改为ME_PROCESS_PO_CUST,这个的接口比较多

image

 因为我们只是校验,一般采用check方法,如果是需要改数据的话,采用PROCESS_HEADER和PROCESS_ITEM

代码如下

  METHOD IF_EX_ME_PROCESS_PO_CUST~CHECK.

    TYPES:BEGIN OF TY_DATA,
            MATNR TYPE EKPO-MATNR,
            MENGE TYPE EKPO-MENGE,
          END OF TY_DATA.
    DATA:LT_DATA_OLD TYPE TABLE OF TY_DATA,
         LS_DATA_OLD TYPE TY_DATA.
    DATA:LT_DATA_NEW TYPE TABLE OF TY_DATA,
         LS_DATA_NEW TYPE TY_DATA.
    DATA: LS_MEPOHEADER TYPE MEPOHEADER,
          R_ITEMS       TYPE PURCHASE_ORDER_ITEMS,
          R_ITEM        TYPE PURCHASE_ORDER_ITEM,
          LT_ITEM       TYPE STANDARD TABLE OF MEPOITEM,
          LS_ITEM       TYPE MEPOITEM.

    DATA: LV_EBELN    TYPE EBELN,
          LT_OLD_EKPO TYPE TABLE OF EKPO.


    CLEAR:   LS_MEPOHEADER,R_ITEMS.
    LS_MEPOHEADER = IM_HEADER->GET_DATA( ).
    R_ITEMS       = IM_HEADER->GET_ITEMS( ).

    LV_EBELN = LS_MEPOHEADER-EBELN.
    "取得原订单的数量
    SELECT MATNR, MENGE
    INTO CORRESPONDING FIELDS OF TABLE @LT_OLD_EKPO
    FROM EKPO
   WHERE EBELN = @LV_EBELN
     AND LOEKZ = ''.  " 仅未删除行

    "合计原订单各物料数量
    LOOP AT LT_OLD_EKPO INTO DATA(LS_EKPO_OLD) .
      MOVE-CORRESPONDING LS_EKPO_OLD TO LS_DATA_OLD.
      COLLECT LS_DATA_OLD INTO LT_DATA_OLD.
      CLEAR:LS_EKPO_OLD,LS_DATA_OLD.
    ENDLOOP.
    "取得修改后的订单数量
    LOOP AT R_ITEMS INTO R_ITEM.
      LS_ITEM = R_ITEM-ITEM->GET_DATA( ).
      MOVE-CORRESPONDING LS_ITEM TO LS_DATA_NEW.
      COLLECT LS_DATA_NEW INTO LT_DATA_NEW.
      CLEAR:LS_ITEM,LS_DATA_NEW.
    ENDLOOP.
    "比较修改前后的数量
    LOOP AT LT_DATA_NEW INTO LS_DATA_NEW.
      READ TABLE LT_DATA_OLD INTO LS_DATA_OLD WITH KEY MATNR = LS_DATA_NEW-MATNR.
      IF LS_DATA_NEW-MENGE > LS_DATA_OLD-MENGE.
        MESSAGE E001(ZMM01) .
      ENDIF.
    ENDLOOP.

  ENDMETHOD.

以上都是类处理,所以没接触过的话怎么获取具体的内表或者工作区是个问题,经过摸索,要根据方法的参数去获取

首先来讲抬头

文中用了LS_MEPOHEADER = IM_HEADER->GET_DATA).这样的表达方式,先去查看check方法的参数,点击check,点参数

image

 可以看到有四个参数,我们使用第一个

image

 它有关联了一个接口类型,理解为这个参数就是一个接口,我们双击关联类型,进去看有哪些方法

image

 我们选择get_data,一样继续看这个方法的参数

image

 这个事后可以看到参考类型是一个结构,说明到这一步可以取到实际的工作区数据了。

所以我们先定义DATA: LS_MEPOHEADER    TYPE    MEPOHEADER.

用LS_MEPOHEADER来接收IM_HEADER中的GET_DATA的数据。

一样的道理,通过和以上差不多的方法可以接收行项目的数据,不过行项目数据比抬头数据多了一层接口

首先也可以到达以上和抬头一样的位置R_ITEMS       = IM_HEADER->GET_ITEMS).

这个时候R_ITEMS 的参考是R_ITEM        TYPE PURCHASE_ORDER_ITEM,

image

 

image

 我们双击关联类型

参考的是PURCHASE_ORDER_ITEM,是一张表结构(这个很关键)

image

 继续双击可以看到这个表里有一个组件,就是一个字段的意思(所以实际要取得这个字段值的话,是要循环这个PURCHASE_ORDER_ITEMS),参考的又是一个接口类型

image

 里面有各种方法

image

 这个取用get_data的方法,查看其参数,可以看到这个时候参考的是一个结构,所以此时是一个工作区数据了

image

 我们代码是分开写的,先取得R_ITEMS       = IM_HEADER->GET_ITEMS).这是一个表,再通过定义 R_ITEM        TYPE PURCHASE_ORDER_ITEM,循环取得工作区, 

工作区里的字段item参考的是一个接口,通过接口方法获取参数,定义LS_ITEM       TYPE MEPOITEM.去接收参数内容

LS_ITEM = R_ITEM-ITEM->GET_DATA).

 

此时可以得到抬头数据,也可以得到行项目数据,再去写逻辑去校验。

 可以看到效果和标准的一样

image

 

posted @ 2025-07-25 09:49  萧静默  阅读(355)  评论(0)    收藏  举报