SAP 采购阶梯价增强

自建表设计,按标准表KONM设计

 

数据维护

五行代表这个物料有五个价格阶梯,采购订单下单时0—1000的数量价格必须是300,1000—5000的数量价格必须是299,5000—7000的数量价格必须是298,7000—10000的数量价格必须是297,10000以上的数量价格必须是296。

 

*┏--------Begin-------- Add By AiQing 20.06.2024 10:06:59 -------------
* --------  ★  --------〔业务顾问:罗仁勇〕
*&--- 采购订单下单控制必须按阶梯价下单
    TYPES:BEGIN OF lty_matnr,
            matnr   TYPE ekpo-matnr,
            menge   TYPE ekpo-menge,
            netwr   TYPE ekpo-netwr,
            message TYPE string,
          END OF lty_matnr.

    DATA lt_matnr_1 TYPE TABLE OF lty_matnr.
    DATA lt_matnr_2 TYPE TABLE OF lty_matnr.
    DATA lt_matnr_3 TYPE TABLE OF lty_matnr.
    DATA lt_matnr_4 TYPE TABLE OF lty_matnr.
    DATA ls_matnr_1 TYPE lty_matnr.
    DATA ls_matnr_2 TYPE lty_matnr.
    DATA ls_matnr_3 TYPE lty_matnr.
    DATA ls_matnr_4 TYPE lty_matnr.

*&--- 存放阶梯价区间的内表
    TYPES:BEGIN OF gty_kstbm,
            low   TYPE zxmmt063-kstbm,
            high  TYPE zxmmt063-kstbm,
            netwr TYPE ekpo-netwr,
          END OF gty_kstbm.

    DATA rt_kstbm TYPE TABLE OF  gty_kstbm.
    DATA rs_kstbm TYPE gty_kstbm.

    CLEAR lt_item.
    IF ls_header-bukrs = '6000' AND sy-tcode = 'ME21N'.

      CALL METHOD im_header->get_items
        RECEIVING
          re_items = lt_purchase_order_item.

      LOOP AT lt_purchase_order_item INTO ls_purchase_order_item.
        "获取行项目数据的类
        cl_item = ls_purchase_order_item-item.

        "获取行项目值
        CLEAR: ls_item.
        CALL METHOD cl_item->get_data
          RECEIVING
            re_data = ls_item.

        APPEND ls_item TO lt_item.

        "【*********按物料维度汇总下单的数量*********】
        CLEAR ls_matnr_1.
        ls_matnr_1-matnr = ls_item-matnr.
        ls_matnr_1-menge = ls_item-menge.
        COLLECT ls_matnr_1 INTO lt_matnr_1.

        "【*********计算总数量的价值*********】
        CLEAR ls_matnr_3.
        ls_matnr_3-matnr = ls_item-matnr.
        ls_matnr_3-netwr = ls_item-menge * ls_item-netpr.
        COLLECT ls_matnr_3 INTO lt_matnr_3.

      ENDLOOP.

      DATA(lt_luru) = lt_matnr_1.

*&--- 按物料汇总历史的采购订单数量
      DATA(lt_item_sum) = lt_item.
      SORT lt_item_sum BY matnr.
      DELETE ADJACENT DUPLICATES FROM lt_item_sum COMPARING matnr.

      SELECT
      a~matnr,
      SUM( a~menge ) AS menge
      FROM
      ekpo AS a
      INNER JOIN ekko AS b
      ON a~ebeln = b~ebeln
      INNER JOIN @lt_item_sum AS c
      ON a~matnr = c~matnr
      WHERE b~lifnr = @ls_header-lifnr
      AND   b~ekorg = @ls_header-ekorg
      AND   a~loekz = ''
      GROUP BY a~matnr
      INTO TABLE @DATA(lt_ekpo)
      .

*&--- 汇总历史的数量+录入的数量
      DATA(lt_ekpo_1) = lt_ekpo.
      LOOP AT lt_ekpo_1 INTO DATA(ls_ekpo_1).
        CLEAR ls_matnr_1.
        MOVE-CORRESPONDING ls_ekpo_1 TO ls_matnr_1.
        COLLECT ls_matnr_1 INTO lt_matnr_1.
      ENDLOOP.

      SORT lt_matnr_1 BY matnr.
      DATA lv_menge2 TYPE ekpo-menge.
      CLEAR lt_matnr_2.
*&--- 按物料维度循环
      LOOP AT lt_matnr_1 INTO ls_matnr_1.

        "读取当前物料录入的数量
        READ TABLE lt_luru INTO DATA(ls_luru) WITH KEY matnr = ls_matnr_1-matnr.

        DATA(lv_luru) = ls_luru-menge.

*┏--------Begin-------- Add By AiQing 23.04.2024 17:13:47 -------------
*&--- 找到物料对应的阶梯价
        SELECT
        c~*,
        b~matnr
        FROM
        a018 AS b
        INNER JOIN zxmmt063 AS c
        ON    b~knumh = c~knumh
        WHERE b~ekorg = @ls_header-ekorg
        AND   b~lifnr = @ls_header-lifnr
        AND   b~datbi > @ls_header-bedat
        AND   b~datab < @ls_header-bedat
        AND   b~matnr = @ls_matnr_1-matnr
        INTO TABLE @DATA(lt_zxmmt063)
        .

        IF sy-subrc <> 0.
          CONTINUE.
        ENDIF.

        DATA lv_index1 TYPE i .
        DATA lv_index2 TYPE i .

        lv_index1 = 1.
        lv_index2 = 2.
        CLEAR rt_kstbm.
        "将阶梯价转换为区间
        DO lines( lt_zxmmt063 ) TIMES.

          CLEAR rs_kstbm.
          LOOP AT lt_zxmmt063 INTO DATA(ls_zxmmt063) FROM lv_index1 TO lv_index2 .
            IF sy-tabix = lv_index1.
              rs_kstbm-low   = ls_zxmmt063-c-kstbm.
              rs_kstbm-netwr = ls_zxmmt063-c-kbetr.
            ELSE.
              rs_kstbm-high = ls_zxmmt063-c-kstbm.
            ENDIF.
          ENDLOOP.

          IF lines( lt_zxmmt063 ) = sy-index.
            rs_kstbm-high = 99999999.
          ENDIF.

          APPEND rs_kstbm TO rt_kstbm.

          lv_index1 = lv_index1 + 1.
          lv_index2 = lv_index2 + 1.
        ENDDO.

        CLEAR:lv_index1,lv_index2.
* -------- End -------------------------------------------------------┛
*        DATA(LV_MENGE4) = LT_EKPO[ 1 ]-MENGE.

*        READ TABLE LT_EKPO INTO DATA(LS_EKPO) WITH KEY MATNR = LS_MATNR_1-MATNR.
*        DATA(LV_MENGE4) = LS_EKPO-MENGE.
*        CLEAR LS_EKPO.
        DATA(lv_menge4) = lt_ekpo[ matnr = ls_matnr_1-matnr ]-menge.

        DATA lv_message TYPE string.
        DATA lv_menge3  TYPE ekpo-menge.
        "将阶梯区间倒序【方便计算多少数量需要按对应的价格下单】
        SORT rt_kstbm BY low DESCENDING.
*        READ TABLE RT_KSTBM ASSIGNING FIELD-SYMBOL(<FS_KSTBM>) INDEX 1.
*        <FS_KSTBM>
        LOOP AT rt_kstbm INTO DATA(rs_kstbm1).

          CLEAR:rs_kstbm,ls_matnr_2.
          MOVE-CORRESPONDING rs_kstbm1 TO rs_kstbm.

          AT FIRST.
            lv_menge2 = ls_matnr_1-menge.
          ENDAT.

          IF ls_matnr_1-menge >= rs_kstbm-low.
            "物料 / 价值
            ls_matnr_2-matnr = ls_matnr_1-matnr.
            ls_matnr_2-netwr = ( lv_menge2 - rs_kstbm-low ) * rs_kstbm-netwr.

            "【*********按采购订单行计算物料的总价值*********】
            IF lv_luru > 0.
              IF lv_luru > ( lv_menge2 - rs_kstbm-low ).
                lv_luru = lv_luru - ( lv_menge2 - rs_kstbm-low ).
                ls_matnr_4-matnr = ls_matnr_1-matnr.
                ls_matnr_4-netwr = ( lv_menge2 - rs_kstbm-low ) * rs_kstbm-netwr.
              ELSEIF lv_luru < ( lv_menge2 - rs_kstbm-low ).
                ls_matnr_4-matnr = ls_matnr_1-matnr.
                ls_matnr_4-netwr = lv_luru * rs_kstbm-netwr.
                lv_luru = lv_luru - ( lv_menge2 - rs_kstbm-low ).
              ENDIF.

              COLLECT ls_matnr_4 INTO lt_matnr_4.
            ENDIF.

            lv_menge3 = lv_menge2 - rs_kstbm-low.

*┏--------Begin-------- Add By AiQing 19.06.2024 21:18:01 -------------
            IF lv_menge3 + lv_menge4 > rs_kstbm-high.
              lv_menge3 = abs( rs_kstbm-high - lv_menge4 ).
              DATA(exit_flag2) = 'X'.
*              CLEAR:LV_MENGE4.
            ENDIF.

            CLEAR ls_luru.
            READ TABLE lt_luru INTO ls_luru WITH KEY matnr = ls_matnr_1-matnr.
            IF sy-subrc = 0 AND lv_menge3 > ls_luru-menge.
              lv_menge3 = ls_luru-menge.
              DATA(exit_flag) = 'X'.
            ENDIF.
* -------- End -------------------------------------------------------┛
            IF lv_menge3 > 0.
              lv_message = |{ lv_message && ',数量:' &&  lv_menge3  && '单价应为' && rs_kstbm-netwr }| .
            ENDIF.

            IF exit_flag = 'X'.
              CLEAR exit_flag.
              EXIT.
            ENDIF.

            CLEAR lv_menge3.
            COLLECT ls_matnr_2 INTO lt_matnr_2.
          ELSE.
            CONTINUE.
          ENDIF.

          lv_menge2 = rs_kstbm-low.

          "如果历史订单数量被清空,说明循环已经走完了,退出循环
          IF exit_flag2 = 'X'.
            EXIT.
          ENDIF.

          CLEAR rs_kstbm.
        ENDLOOP.

        ls_matnr_2-message = lv_message.
        MODIFY lt_matnr_2 FROM ls_matnr_2 TRANSPORTING message WHERE matnr = ls_matnr_1-matnr.

        CLEAR:ls_matnr_1,
              lt_zxmmt063.
      ENDLOOP.
*&--- 拆分消息
      IF lv_message IS NOT INITIAL.
        SPLIT lv_message AT ',' INTO TABLE DATA(lt_message).
        DELETE lt_message INDEX 1.
      ENDIF.

      "对比按总数量计算的总价值和按采购订单行计算汇总的总价值,如果不一致则报错
      LOOP AT lt_matnr_4 INTO ls_matnr_4.

        READ TABLE lt_matnr_3 INTO ls_matnr_3 WITH KEY matnr = ls_matnr_4-matnr.

        IF sy-subrc = 0.

          IF ls_matnr_3-netwr <> ls_matnr_4-netwr.

            LOOP AT lt_message INTO DATA(ls_message).
*           设置当前消息的主体为行项目
              mmpur_business_obj cl_item.
*             物料XXXXXX应按建议阶梯拆分数量下单,数量ZSYJTJYSL单价应为ZSYJTJYJG!、数量ZDQJTJYSL单价应为ZDQJTJYJG
              MESSAGE e145(zmm) WITH ls_matnr_4-matnr && ls_message INTO lv_dummy.
              ch_failed = abap_true.
              mmpur_message_forced 'E' 'ZMM' '145' sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4..
            ENDLOOP.

          ENDIF.

          CLEAR ls_matnr_3.
        ENDIF.

        CLEAR ls_matnr_4.
      ENDLOOP.

    ENDIF.

 

posted @ 2024-06-25 19:51  艾靑  阅读(105)  评论(0编辑  收藏  举报