欢迎来到萧静默的博客

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

关于SAP采购发票增强

1、se18里的invoice update增强,一般使用里面的三个方法

image

 参考代码

  method if_ex_invoice_update~change_at_save.
    """I_UPDATE_FLAG I 代表新建、D代表删除、U代表更新 通过此标记区分预制发票的增删改操作

    data lt_zmmt008 type table of zmmt008.
    data lv_wmwst type zmmt008-wmwst.
    data lv_wrbtr type zmmt008-wrbtr.
    data lv_zkaig type j_inact.
    data lv_msg TYPE string.

    clear lv_zkaig.

    clear :lt_zmmt008,lv_wmwst,lv_wrbtr,lv_msg.

    call function 'ZUSER_EXIT'
      exporting
        zzqxh = '124'
      importing
        zkaig = lv_zkaig.

    if lv_zkaig ne 'X'.

      "当含预制发票含税金额、税额与发票参考含税金额、税额不一致时,弹出消息提醒
      call function 'ZMM_GET_INVOICE'
        tables
          out = lt_zmmt008.

      if lt_zmmt008 is initial .
        select * into table lt_zmmt008 from zmmt008 where belnr = s_rbkp_new-belnr and  gjahr = s_rbkp_new-gjahr.
      endif.

      loop at lt_zmmt008 into data(lw_zmmt008) where zchk = 'X'.
        lv_wmwst = lv_wmwst + lw_zmmt008-wmwst.
        lv_wrbtr = lv_wrbtr  + lw_zmmt008-wrbtr.
      endloop.

      if lt_zmmt008 is not initial.

        if  lv_wrbtr ne   s_rbkp_new-rmwwr.
          lv_msg = '金额'.
        endif.

        if lv_wmwst ne s_rbkp_new-wmwst1 .
          if lv_msg is initial .

            lv_msg = '税额'.
          else.

            lv_msg =  lv_msg && '、税额'.
          endif.

        endif.

        if lv_msg is not initial.
          message i008(zmm001) with lv_msg.
        endif.

      endif.

      clear: lv_wmwst,lv_wrbtr,lt_zmmt008,lv_msg.

    endif.


    "增加校验 余额不等于0时不能保存
*    if sy-ucomm = 'PARK' .
*      field-symbols: <differenz>  type rm08m-differenz.
*      " FREE <differenz>.
*      assign ('(SAPLMR1M)RM08M-DIFFERENZ') to <differenz>.
*      if <differenz> ne 0.
*        message  e005(zmm001).
*      endif.
*    endif.

    if  sy-ucomm = 'PARK' and i_update_flag <> 'I' .
      "根据预制发票状态(自定义表)去判断是否允许保存,已经发送至FSSC的数据禁止修改增强
      select single *  into @data(wa_009)  from zmmt009 where belnr = @s_rbkp_new-belnr and gjahr =  @s_rbkp_new-gjahr .
      if sy-subrc = 0.
        if wa_009-status <> 'B' and wa_009-sucess = 'true'.
          message  e002(zmm001).
          return.
        endif.
      endif.
    endif.

    if sy-ucomm = 'BU' and sy-uname ne 'PORFC'."过账校验
      select count(*) from zmmt009 where belnr = s_rbkp_new-belnr and gjahr = s_rbkp_new-gjahr and sucess = 'ture' .
      if sy-subrc = 0.
        message  e000(zmm001).
      endif.
    endif.

    if sy-ucomm = 'DELE' and i_update_flag = 'D' and sy-uname ne 'PORFC'."删除校验
      select count(*) from zmmt009 where belnr = s_rbkp_new-belnr and gjahr = s_rbkp_new-gjahr and sucess = 'ture' .
      if sy-subrc = 0.
        message  e003(zmm001).
      endif.
    endif.
    if sy-ucomm = 'DELE' .
      data: i_zmmr002 type zmmr002 .
      data: iporg     type msxxlist-hostadr,
            ipdec(16) type c,
            host(18)  type c.
** Get user IP,hostname
      call function 'TH_USER_INFO'  " Get user IP,hostname
        exporting
          client   = sy-mandt
          user     = sy-uname
        importing
          hostaddr = iporg
          terminal = host
        exceptions
          others   = 1.
*    *"Conv.IP addr to format "xxx.xxx.xxx.xxx"
      call function 'GWY_IPADR2STRING'   "Conv.IP addr
        exporting
          ipadr  = iporg
        importing
          string = ipdec.
*    **Common var.
      call method cl_system_uuid=>if_system_uuid_static~create_uuid_c32
        receiving
          uuid = data(lv_uuid).
      move: sy-mandt to i_zmmr002-mandt,
            sy-uname to i_zmmr002-aenam,
            sy-datum to i_zmmr002-laeda,
            sy-uzeit to i_zmmr002-times,
            sy-tcode to i_zmmr002-tcode,
            ipdec    to i_zmmr002-hostip,
            host     to i_zmmr002-host,
            s_rbkp_new-belnr to i_zmmr002-belnr,
            s_rbkp_new-gjahr to i_zmmr002-gjahr,
            lv_uuid to i_zmmr002-uuid.
      modify zmmr002 from i_zmmr002 .

    endif.

    if sy-ucomm = 'CANC' and sy-uname ne 'PORFC' ."冲销校验
      select count(*) from zmmt009 where belnr = s_rbkp_new-belnr and gjahr = s_rbkp_new-gjahr and sucess = 'ture' .
      if sy-subrc = 0.
        message  e001(zmm001).
      endif.
    endif.

    if  sy-ucomm = 'PARK' and s_rbkp_new-bktxt is initial .

*      S_RBKP_NEW-BKTXT =  S_RBKP_NEW-SGTXT .

      if  s_rbkp_new-sgtxt is   initial.
        message  e004(zmm001).
      endif.

    endif.

  endmethod.
  method if_ex_invoice_update~change_before_update.


    if sy-ucomm = 'PARK' or ( sy-ucomm = 'BU' and  sy-tcode    = 'MIRO' ) .

      call function 'ZMM_SAVE_INVOICE'
        exporting
          s_rbkp_new = s_rbkp_new.
    endif.
    if   sy-ucomm = 'PARK'  or ( sy-ucomm = 'BU' and  sy-tcode  = 'MIRO' ) and s_rbkp_new-zchk_send is initial . "  "保存时推送数据至FSSC ""默认推送
      select single *  into @data(wa_009)  from zmmt009 where belnr = @s_rbkp_new-belnr and gjahr =  @s_rbkp_new-gjahr .
      case wa_009-type.
        when ''.
          wa_009-type =  '01' .
        when '01' .
          if wa_009-sucess =  'ture'  .
            wa_009-type =  '02' .
          else.
            if wa_009-status = '' .
              wa_009-type =  '01' .
            else.
              wa_009-type =  '02' .
            endif.
          endif.
        when '02' .

        when others.
      endcase.


      call function 'Z_CHECK_RBKP' starting new task 'ZCHECK_RBKP'
        exporting
          belnr   = s_rbkp_new-belnr
          gjahr   = s_rbkp_new-gjahr
          is_flag = wa_009-type.

*      call function 'ZFSSC_007' "IN BACKGROUND TASK
*        exporting
*          is_rbkp = s_rbkp_new
*          is_flag = wa_009-type
*        tables
*          it_rseg = ti_mrmrseg.

    endif.

    "增强开关
    select count(*) from zuser_exit where zzqxh = '103' and zkaig eq space.
    if sy-subrc = 0.
      "发票变更:过账 冲销时 发送数据给FSSC "porfc-接口(bapi)  bu-过账  CANC-冲销
      data :lt_rseg type table of mrmrseg..
      clear lt_rseg[].
      if sy-uname = 'PORFC' or  sy-ucomm = 'BU' or sy-ucomm = 'CANC' .
        lt_rseg[] = ti_mrmrseg[].
        delete lt_rseg where ebeln is initial.
        sort lt_rseg by ebeln.
        delete adjacent duplicates from lt_rseg comparing ebeln.

        loop at lt_rseg into data(lw_rseg).
          call function 'ZFSSC_028' in background task
            exporting
              ebeln = lw_rseg-ebeln
              wait  = 'X'.
        endloop.
      endif.
    endif.

    if sy-ucomm = 'DELE'  . "预制发票删除  取消发票参考关联 ""修复选中异常 
      update zmmt008 set incoiceid =  '' ,  belnr = '' ,  gjahr = '' , zchk =  ''  where  belnr = @s_rbkp_new-belnr and gjahr =  @s_rbkp_new-gjahr .
    endif.

    if sy-ucomm = 'CANC'  ."冲销   取消发票参考关联
      update zmmt008 set incoiceid =  '' ,  belnr = '' ,  gjahr = '' , zchk =  ''  where  belnr = @s_rbkp_new-belnr and gjahr =  @s_rbkp_new-gjahr .
    endif.

  endmethod.

2、还一个是CMOD里的增强

image

 代码参考

*&---------------------------------------------------------------------*
*& 包含               ZXM08U30
*&---------------------------------------------------------------------*
DATA:BEGIN OF GW_EKBE,
       EBELN TYPE EKBE-EBELN,
       EBELP TYPE EKBE-EBELP,
       BEWTP TYPE EKBE-BEWTP,
       MENGE TYPE EKBE-MENGE,
       SHKZG TYPE EKBE-SHKZG,
       BELNR TYPE EKBE-BELNR,
       BUZEI TYPE EKBE-BUZEI,

     END OF GW_EKBE.
DATA:BEGIN OF GW_EKBE_C,
       EBELN TYPE EKBE-EBELN,
       EBELP TYPE EKBE-EBELP,
       BEWTP TYPE EKBE-BEWTP,
       MENGE TYPE EKBE-MENGE,
     END OF GW_EKBE_C.
DATA:BEGIN OF GW_TI_DRSEG_C,
       EBELN   TYPE EKBE-EBELN,
       EBELP   TYPE EKBE-EBELP,
       MENGE   TYPE EKBE-MENGE,
       VORGANG TYPE MRM_VORGANG,
     END OF GW_TI_DRSEG_C.

DATA:GT_EKBE LIKE STANDARD TABLE OF GW_EKBE.
DATA:GT_EKBE_C LIKE STANDARD TABLE OF GW_EKBE_C.
DATA:GT_TI_DRSEG_C LIKE STANDARD TABLE OF GW_TI_DRSEG_C.
DATA:LV_ZKAIG TYPE J_INACT.
DATA:WA_EKGRP TYPE EKKO-EKGRP.
CHECK SY-TCODE = 'MIR7'.

CALL FUNCTION 'ZUSER_EXIT'
  EXPORTING
    ZZQXH = '17'
  IMPORTING
    ZKAIG = LV_ZKAIG.

READ TABLE  TI_DRSEG INTO DATA(LS_EKGRP) INDEX 1.
WA_EKGRP = LS_EKGRP-EKGRP.

IF ( I_RBKPV-BUKRS = '1010' OR I_RBKPV-BUKRS = '1030' OR I_RBKPV-BUKRS = '1020' )
  
  AND WA_EKGRP <> 'X08'
  .

  IF LV_ZKAIG = ''.
    E_RELEASE_YN = 'Y'.
    SELECT
      EBELN
      EBELP
      BEWTP
      MENGE
      SHKZG
      BELNR
      BUZEI
      FROM EKBE
      INTO CORRESPONDING FIELDS OF TABLE GT_EKBE
      FOR ALL ENTRIES IN TI_DRSEG
      WHERE EBELN = TI_DRSEG-EBELN
      AND EBELP = TI_DRSEG-EBELP
      AND BEWTP IN ('E','Q','T').

    LOOP AT  GT_EKBE ASSIGNING FIELD-SYMBOL(<FS_EKBE>).
      MOVE-CORRESPONDING <FS_EKBE> TO GW_EKBE_C.
      IF <FS_EKBE>-SHKZG = 'H'.
        GW_EKBE_C-MENGE =     GW_EKBE_C-MENGE * -1.
      ENDIF.
      COLLECT GW_EKBE_C INTO GT_EKBE_C.
      CLEAR GW_EKBE_C.
    ENDLOOP.

    LOOP AT TI_DRSEG ASSIGNING FIELD-SYMBOL(<FS_DRSEG>).
      MOVE-CORRESPONDING <FS_DRSEG> TO GW_TI_DRSEG_C.
      COLLECT GW_TI_DRSEG_C INTO GT_TI_DRSEG_C.
      CLEAR GW_TI_DRSEG_C.
    ENDLOOP.

    SORT GT_EKBE_C BY EBELN EBELP BEWTP.

    DATA:E_MENGE TYPE MENGE_D.
    DATA:Q_MENGE TYPE MENGE_D.
    DATA:T_MENGE TYPE MENGE_D.
    LOOP AT GT_TI_DRSEG_C ASSIGNING FIELD-SYMBOL(<FS_DRSEG_C>).
      CLEAR:E_MENGE,Q_MENGE,T_MENGE.
      READ TABLE GT_EKBE_C  ASSIGNING FIELD-SYMBOL(<FS_EKBE_C>) WITH KEY EBELN = <FS_DRSEG_C>-EBELN EBELP = <FS_DRSEG_C>-EBELP  BEWTP = 'E' BINARY SEARCH.
      IF SY-SUBRC = 0.
        E_MENGE = <FS_EKBE_C>-MENGE.
      ENDIF.

      READ TABLE GT_EKBE_C  ASSIGNING <FS_EKBE_C> WITH KEY EBELN = <FS_DRSEG_C>-EBELN EBELP = <FS_DRSEG_C>-EBELP  BEWTP = 'Q' BINARY SEARCH.
      IF SY-SUBRC = 0.
        Q_MENGE = <FS_EKBE_C>-MENGE.
      ENDIF.

      READ TABLE GT_EKBE_C  ASSIGNING <FS_EKBE_C> WITH KEY EBELN = <FS_DRSEG_C>-EBELN EBELP = <FS_DRSEG_C>-EBELP  BEWTP = 'T' BINARY SEARCH.
      IF SY-SUBRC = 0.
        T_MENGE = <FS_EKBE_C>-MENGE.
      ENDIF.


      IF I_RBKPV-XRECH = 'X'.
        IF I_RBKPV-TBTKZ = SPACE.
          <FS_DRSEG_C>-VORGANG = 1.
        ELSE.
          <FS_DRSEG_C>-VORGANG = 3.
        ENDIF.
      ELSE.
        IF I_RBKPV-TBTKZ = SPACE.
          <FS_DRSEG_C>-VORGANG = 2.
        ELSE.
          <FS_DRSEG_C>-VORGANG = 4.
        ENDIF.
      ENDIF.
      IF <FS_DRSEG_C>-VORGANG = 1.
        "当前录入数量 > 累计所有采购收货数量-累计所有采购发票校验数量-累计所有发票预制数量
        "当前录入数量 > E - Q - T
        IF <FS_DRSEG_C>-MENGE > ( E_MENGE - Q_MENGE - T_MENGE   ).
          E_RELEASE_YN = 'N'.
          MESSAGE '发票预制数量已超过采购收货数量,请检查累计发票校验和预制数量' TYPE 'E'.
          RETURN.
        ENDIF.
      ELSEIF <FS_DRSEG_C>-VORGANG = 2.
        E_MENGE = E_MENGE * -1.
        Q_MENGE = Q_MENGE * -1.
        T_MENGE = T_MENGE * -1.
        IF <FS_DRSEG_C>-MENGE > ( E_MENGE - Q_MENGE - T_MENGE   ).
          E_RELEASE_YN = 'N'.
          MESSAGE '发票预制数量已超过采购收货数量,请检查累计发票校验和预制数量' TYPE 'E'.
          RETURN.
        ENDIF.
      ENDIF.

    ENDLOOP.
  ENDIF.
ENDIF.


"校验单个物料凭证可预制数量
CLEAR LV_ZKAIG.
CALL FUNCTION 'ZUSER_EXIT'
  EXPORTING
    ZZQXH = '123'
  IMPORTING
    ZKAIG = LV_ZKAIG.


DATA:LV_MENGE  TYPE MSEG-MENGE,
     LV_MENGE1 TYPE MSEG-MENGE,
     LV_MENGE2 TYPE MSEG-MENGE.

DATA LV_INDEX TYPE I.


IF LV_ZKAIG NE 'X'.
  LOOP AT TI_DRSEG INTO DATA(LW_RSEG) WHERE LFBNR IS NOT INITIAL .

    LV_INDEX = SY-TABIX.

    CLEAR :LV_MENGE,LV_MENGE1,LV_MENGE2.

    SELECT  SUM( ( CASE A~SHKZG WHEN 'S' THEN A~MENGE ELSE A~MENGE * -1 END ) ) AS MENGE
      INTO @LV_MENGE1
      FROM RSEG AS A
      INNER JOIN RBKP AS B ON A~BELNR = B~BELNR AND A~GJAHR = B~GJAHR
     WHERE A~LFBNR = @LW_RSEG-LFBNR
      AND  A~LFGJA = @LW_RSEG-LFGJA
      AND A~LFPOS = @LW_RSEG-LFPOS
      AND B~RBSTAT NE '2'.

    SELECT SINGLE ERFMG
        INTO @LV_MENGE2
         FROM MSEG
        WHERE MBLNR = @LW_RSEG-LFBNR
        AND  MJAHR = @LW_RSEG-LFGJA
         AND ZEILE = @LW_RSEG-LFPOS.

    LV_MENGE = LV_MENGE2 - LV_MENGE1.

    IF LW_RSEG-MENGE > LV_MENGE.

      IF LV_MENGE < 0.
        LV_MENGE = 0.
      ENDIF.
      E_RELEASE_YN = 'N'.
      MESSAGE '' && LV_INDEX && '行,物料凭证' && LW_RSEG-LFBNR && '行项目' && LW_RSEG-LFPOS && '可预制数量为' &&  LV_MENGE TYPE 'E'.
      RETURN.

    ENDIF.

  ENDLOOP.
ENDIF.

 

posted @ 2026-01-30 11:29  萧静默  阅读(1)  评论(0)    收藏  举报